- •3.2. Протокол доставки пользовательских дейтаграмм udp
- •5. Рабочее задание и указание к его выполнению
- •Цель работы
- •Подготовка к работе
- •Стек протоколов tcp/ip
- •3.1. Протокол межсетевого взаимодействия ip, формат ip пакета.
- •3.2. Протокол доставки пользовательских дейтаграмм udp.
- •3.3. Протокол надежной доставки сообщений tcp
- •Программирование по схеме “клиент-сервер” с использованием интерфейса Windows Sockets
- •Int wsaStartup(word wVersionRequested, lpwsadata lpWsaData);
- •Int wsaCleanup(void);
- •Int wsaGetLastError(void);
- •Socket socket(int af, int type, int protocol);
- •Int closesocket(socket sock);
- •Char far * inet_ntoa(struct in_addr in);
- •#Define h_addr h_addr_list[0]
- •Int bind(socket s, const struct sockaddr far *name, int namelen);
- •Int listen(socket sock, int backlog);
- •Socket accept(socket s, struct sockaddr far *addr, int far * addrlen);
- •Void ExitThread(uint fuExitCode);
- •Bool TerminateThread(handle hThread, dword dwExitCode);
- •Connect (socket s, const struct sockaddr *peer, int peer_len);
- •Передача и приём данных.
- •Int sendto(socket s,const void* buf, size_t len, int flags,
- •Int recvfrom(socket s,void* buf,size_t len, int flags,
- •Алгоритм построения клиента и сервера.
- •5. Рабочее задание и указание к его выполнению.
- •Содержание отчёта.
- •Вопросы для самопроверки.
- •8. Библиографический список
Char far * inet_ntoa(struct in_addr in);
При ошибке эта функция возвращает NULL.
Однако чаще всего пользователь работает с доменными именами, применяя сервер DNS или файл HOSTS(пример файла приведен ниже).
# (C) Корпорация Майкрософт (Microsoft Corp.), 1993-1999 # # Это образец файла HOSTS, используемый Microsoft TCP/IP для #Windows. # Этот файл содержит сопоставления IP-адресов именам узлов. # Каждый элемент должен располагаться в отдельной строке. IP-#адрес должен # находиться в первом столбце, за ним должно следовать #соответствующее имя. # IP-адрес и имя узла должны разделяться хотя бы одним пробелом. # Кроме того, в некоторых строках могут быть вставлены #комментарии # (такие, как эта строка), они должны следовать за именем узла и #отделяться # от него символом '#'. # Например: # # 102.54.94.97 rhino.acme.com # исходный сервер # 38.25.63.10 x.acme.com # узел клиента x
127.0.0.1 localhost 172.16.1.3 node |
В этом случае вначале нужно воспользоваться функцией gethostbyname, возвращающей IP адрес, а затем записать полученный IP адрес в структуру sin_addr:
SOCKADDR_IN dest_sin; 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_lenght); |
В случае ошибки функция gethostbyname возвращает NULL. При этом причину ошибки можно выяснить, проверив код возврата функции WSAGetLastError.
Если же указанный узел найден в базе DNS или в файле HOSTS, функция gethostbyname возвращает указатель на структуру hostent, описанную ниже:
struct hostent { char FAR * h_name; //имя узла char FAR * FAR * h_aliases; //список //альтернативных имён short h_addrtype; //тип адреса узла short h_length; //длина адреса char FAR * FAR * h_addr_list //список указателей // на IP-адреса }; typedef struct hostent *PHOSTENT; typedef struct hostent FAR *LPHOSTENT; |
Как и в случае с in_addr, во множестве программ и прилагаемых к Winsock SDK примерах активно используется недокументированное поле структуры h_addr. Например, вот строка из файла "simplec.c":
memcpy(&(server.sin_addr),hp->h_addr,hp->h_length);
В "winsock2.h", можно найти, что обозначает h_addr:
#Define h_addr h_addr_list[0]
Т.е. искомый адрес находиться в h_addr_list[0]. А для чего нужны остальные адреса в списке? Дело в том, что с некоторыми доменными именами связано сразу несколько IP-адресов. В случае неработоспособности одного узла, клиент может попробовать подключиться к другому, или просто выбрать узел с наибольшей скоростью обмена. Но в приведенном примере клиент использует только первый IP-адрес в списке и игнорирует все остальные! Конечно, это не важно в данной лабораторной работе, но использование такой возможности может заметно повысить производительность приложения.
Привязка адреса к сокету.
После инициализации сокета следует произвести привязку адреса интерфейса и номера порта к сокету при помощи функции bind:
