Семинары (1171138), страница 9

Файл №1171138 Семинары (Семинары) 9 страницаСеминары (1171138) страница 92020-04-27СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 9)

Дальнейший анализ причин ошибкиследует выполнять при помощи функции WSAGetLastErrorПеред использованием необходимо задать параметры сокета.Для этого нужно подготовить структуру типа sockaddr , определение которой показано ниже:struct sockaddr{u_short sa_family;char sa_data[14];};Для работы с адресами в формате Internet используется другой вариант этой структуры, в которомдетализируется формат поля sa_data:struct sockaddr_in{short sin_family;u_short sin_port;struct in_addr sin_addr;char sin_zero[8];};sin_family - определяет тип адреса. Вы должны записать в это поле значение AF_INET , которое соответствуеттипу адреса, принятому в Internet:srv_address.sin_family = AF_INET ;Поле sin_port определяет номер порта, который будет использоваться для передачи данных.Особенностью поля sin_port является использование так называемого сетевого формата данных. Этот форматотличается от того, что принят в процессорах с архитектурой Intel, а именно, младшие байты данных хранятсяпо старшим адресам памяти.

Напомним, что архитектура процессоров Intel подразумевает хранение старщихбайтов данных по младшим адресам.Для выполнения преобразований из обычного формат в сетевой и обратно в интерфейсе Windows Socketsпредусмотрен специальный набор функций. В частности, для заполнения поля sin_port нужно использоватьфункцию htons, выполняющую преобразование 16-разрядных данных из формата Intel в сетевой формат.Ниже показано, как инициализируется поле sin_port в приложении SERVER:#define SERV_PORT 5000srv_address.sin_port = htons(SERV_PORT);Вернемся снова к структуре sockaddr_in .Поле sin_addr этой структуры представляет собой структуру in_addr:struct in_addr{union{struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;struct { u_short s_w1,s_w2; } S_un_w;u_long S_addr;} S_un;};При инициализации сокета в этой структуре нужно указать адрес IP, с которым будет работать данный сокет.Если сокет будет работать с любым адресом (например, вы создаете сервер, который будет доступен из узлов слюбым адресом), адрес для сокета можно указать следующим образом:srv_address.sin_addr .s_addr = INADDR_ANY ;В том случае, если сокет будет работать с определенным адресом IP (например, вы создаете приложениеклиент, которое будет обращаться к серверу с конкретным адресом IP), в указанную структуру необходимозаписать реальный адрес.5Датаграммный протокол UDP позволяет посылать пакеты данных одновременно всем рабочим станциям вшироковещательном режиме.

Для этого вы должны указать адрес как INADDR_BROADCAST.Если вам известен адрес в виде четырех десятичных чисел, разделенных точкой (именно так его вводитпользователь), то вы можете заполнить поле адреса при помощи функции inet_addr :dest_sin.sin_addr .s_addr = inet_addr ("200.200.200.201");В случае ошибки функция возвращает значение INADDR_NONE , что можно использовать для проверки.Обратное преобразование адреса IP в текстовую строку можно при необходимости легко выполнить с помощьюфункции inet_ntoa , имеющей следующий прототип:char FAR * inet_ntoa (struct in_addr in);При ошибке эта функция возвращает значение NULL.Однако чаще всего пользователь работает с доменными именами, используя сервер DNS или файл HOSTS . Вэтом случае вначале вы должны воспользоваться функцией gethostbyname , возвращающей адрес IP, а затемзаписать полученный адрес в структуру sin_addr :PHOSTENT phe;phe = gethostbyname ("ftp.microsoft.com");if(phe == NULL){closesocket (srv_socket);MessageBox(NULL, "gethostbyname Error", "Error", MB_OK);return;}memcpy((char FAR *)&(dest_sin.sin_addr ),phe->h_addr , phe->h_length);В случае ошибки функция gethostbyname возвращает NULL.

При этом причину ошибки можно выяснить,проверив код возврата функции WSAGetLastError .#include <stdio.h>#include <iostream>#include <fstream>#include <string.h>#include <winsock2.h>#include <windows.h>using namespace std;#define PORT 777int main(int argc, char* argv[]){char buff[1024];printf("TCP DEMO CLIENT\n");// Шаг 1 - инициализация библиотеки Winsockif (WSAStartup(0x202,(WSADATA *)&buff[0])){printf("WSAStart error %d\n",WSAGetLastError());return -1;}char srv[15];cout << "Server adress: \n";cin >> srv;srv[sizeof(srv)]=0;cout << srv << "\n";// Шаг 2 - создание сокета6SOCKET my_sock;my_sock=socket(AF_INET,SOCK_STREAM,0);if (my_sock<0){printf("Socket() error %d\n",WSAGetLastError());return -1;}// Шаг 3 - установка соединения// заполнение структуры sockaddr_in – указание адреса и портасервераsockaddr_in dest_addr;dest_addr.sin_family=AF_INET;dest_addr.sin_port=htons(PORT);HOSTENT *hst;// преобразование IP адреса из символьного в сетевой формат//if (inet_addr(SERVERADDR)!=INADDR_NONE)if (inet_addr(srv)!=INADDR_NONE)//dest_addr.sin_addr.s_addr=inet_addr(SERVERADDR);dest_addr.sin_addr.s_addr=inet_addr(srv);else// попытка получить IP адрес по доменному имени сервера//if (hst=gethostbyname(SERVERADDR))if (hst=gethostbyname(srv))// hst->h_addr_list содержит не массив адресов, а массивуказателей на адреса((unsigned long *)&dest_addr.sin_addr)[0]=((unsigned long **)hst>h_addr_list)[0][0];else{//printf("Invalid address %s\n",SERVERADDR);printf("Invalid address %s\n",srv);closesocket(my_sock);WSACleanup();return -1;}}Результат выполненияПример 3: Создание канала связи: клиентЕсли вы собираетесь передавать датаграммные сообщения при помощи протокола негарантированной доставкиUDP , канал связи не нужен.

Сразу после создания сокетов и их инициализации можно приступать к передачеданных. Но для передачи данных с использованием протокола TCP необходимо создать канал связи.Со стороны клиента связь устанавливается с помощью стандартной функции connect:int connect (SOCKET s, const struct sockaddr FAR* name, int namelen7Клиент:Первый слева аргумент - дескриптор сокета, возращенный функцией socket; второй - указатель на структуру"sockaddr", содержащую в себе адрес и порт удаленного узла, с которым устанавливается соединение.Структура sockaddr используется множеством функций, поэтому ее описание вынесено в отдельный раздел"Адрес раз, адрес два...". Последний аргумент сообщает функции размер структуры sockaddr.Если по каким-то причинам это сделать не удастся (адрес задан неправильно, узел не существует или "висит",компьютер находится не в сети), функция возвратит ненулевое значение.Клиент:после того как соединение установлено, потоковые сокеты могут обмениваться с удаленным узлом данными,вызывая функции "int send (SOCKET s, const char FAR * buf, int len,int flags)" и "int recv (SOCKET s, char FAR*buf, int len, int flags)" для посылки и приема данных соответственно.Функция send возвращает управление сразу же после ее выполнения, независимо от того, получила липринимающая сторона наши данные или нет.Функция же recv возвращает управление только после того, какполучит хотя бы один байт.Работой обоих функций можно управлять с помощью флагов, передаваемых в одной переменной типа intтретьим слева аргументом.

Эта переменная может принимать одно из двух значений: MSG_PEEK и MSG_OOB.Флаг MSG_PEEK заставляет функцию recv просматривать данные вместо их чтения. Просмотр в отличие отчтения не уничтожает просматриваемые данные. Некоторые источники утверждают, что при взведенном флагеMSG_PEEK функция recv не задерживает управления, если в локальном буфере нет данных, доступных длянемедленного получения. Это неверно! Аналогично, иногда приходится встречать откровенно ложноеутверждение о том, что якобы функция send со взведенным флагом MSG_PEEK возвращает количество ужепереданных байт (вызов send не блокирует управления).

На самом деле функция send игнорирует этот флаг!Флаг MSG_OOB предназначен для передачи и приема срочных (Out Of Band) данных. Срочные данные неимеют преимущества перед другими при пересылке по сети, а всего лишь позволяют оторвать клиента отнормальной обработки потока обычных данных и сообщить ему "срочную" информацию. Если данныепередавались функцией send с установленным флагом MSG_OOB, для их чтения флаг MSG_OOB функции recvтакже должен быть установлен.Дейтаграммный сокет также может пользоваться функциями send и recv, если предварительно вызовет connectно у него есть и свои, "персональные", функции: "int sendto (SOCKET s, const char FAR * buf, int len, int flags,const struct sockaddr FAR * to, int tolen)" и "int recvfrom (SOCKET s, char FAR* buf, int len, int flags, structsockaddr FAR* from, int FAR* fromlen)".Они очень похожи на send и recv - разница лишь в том, что sendto и recvfrom требуют явного указания адресаузла, принимаемого или передаваемого данные.

Вызов recvfrom не требует предварительного задания адресапередающего узла - функция принимает все пакеты, приходящие на заданный UDP-порт со всех IP-адресов ипортов. Напротив, отвечать отправителю следует на тот же самый порт откуда пришло сообщение. Посколькуфункция recvfrom заносит IP-адрес и номер порта клиента после получения от него сообщения, программистуфактически ничего не нужно делать - только передать sendto тот же самый указатель на структуру sockaddr,который был ранее передан функции recvfrem, получившей сообщение от клиента.Во всем остальном обе пары функций полностью идентичны и работают с теми самыми флагами - MSG_PEEKи MSG_OOB.Все четыре функции при возникновении ошибки возвращают значение SOCKET_ERROR (== -1).// пример простого UDP-клиента#include <stdio.h>#include <string.h>#include <winsock2.h>#include <windows.h>#pragma comment(lib, "Ws2_32.lib")#define PORT 777#define SERVERADDR "127.0.0.1"int main(int argc, char* argv[]){char buff[10 * 1014];printf("UDP DEMO Client\nType quit to quit\n");// Шаг 1 - иницилизация библиотеки Winsocks8if (WSAStartup(0x202, (WSADATA *)&buff[0])){printf("WSAStartup error: %d\n", WSAGetLastError());return -1;}// Шаг 2 - открытие сокетаSOCKET my_sock = socket(AF_INET, SOCK_DGRAM, 0);if (my_sock == INVALID_SOCKET){printf("socket() error: %d\n", WSAGetLastError());WSACleanup();return -1;}// Шаг 3 - обмен сообщений с серверомHOSTENT *hst;sockaddr_in dest_addr;dest_addr.sin_family = AF_INET;dest_addr.sin_port = htons(PORT);// определение IP-адреса узлаif (inet_addr(SERVERADDR) != INADDR_NONE)dest_addr.sin_addr.s_addr = inet_addr(SERVERADDR);else{if (hst = gethostbyname(SERVERADDR))dest_addr.sin_addr.s_addr = ((unsigned long **) hst>h_addr_list)[0][0];else{printf("Unknown host: %d\n", WSAGetLastError());closesocket(my_sock);WSACleanup();return -1;}}while (1){// чтение сообщения с клавиатурыprintf("S<=C:"); fgets(&buff[0], sizeof(buff) - 1, stdin);if (!strcmp(&buff[0], "quit\n")) break;// Передача сообщений на серверsendto(my_sock, &buff[0], strlen(&buff[0]), 0, \(sockaddr *)&dest_addr, sizeof(dest_addr));// Прием сообщения с сервераsockaddr_in server_addr;int server_addr_size = sizeof(server_addr);int n = recvfrom(my_sock, &buff[0], sizeof(buff) - 1, 0, \9(sockaddr *)&server_addr, &server_addr_size);if (n == SOCKET_ERROR){printf("recvfrom() error: %d\n", WSAGetLastError());closesocket(my_sock);WSACleanup();return -1;}buff[n] = 0;// Вывод принятого с сервера сообщения на экранprintf("S=>C:%s", &buff[0]);}// Шаг последний - выходclosesocket(my_sock);WSACleanup();return 0;}Скопмилировать udp-клиент и запустить.

Характеристики

Тип файла
PDF-файл
Размер
788,91 Kb
Материал
Тип материала
Высшее учебное заведение

Список файлов семинаров

Свежие статьи
Популярно сейчас
Зачем заказывать выполнение своего задания, если оно уже было выполнено много много раз? Его можно просто купить или даже скачать бесплатно на СтудИзбе. Найдите нужный учебный материал у нас!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
6455
Авторов
на СтудИзбе
305
Средний доход
с одного платного файла
Обучение Подробнее