- •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. Библиографический список
Void ExitThread(uint fuExitCode);
У этой функции нет возвращаемого значения, ведь после ее вызова поток перестает существовать. В параметр fuExitCode она помещает код завершения потока. Функция вызывается из завершаемого потока.
Bool TerminateThread(handle hThread, dword dwExitCode);
Функция завершает поток, идентифицируемый параметром hThread, и помещает код завершения в dwExitCode. Ее используют лишь в крайнем случае, когда управление потоком потеряно. Вызов осуществляется из другого потока.
Пример использования accept:
#define MAXCONNECT 100 SOCKADDR_IN s_addr_out[MAXCONNECT]; DWORD WINAPI ServerAccept(LPVOID); SOCKET sock, socket[MAXCONNECT]; ………………………… int main() { ………………………… DWORD DwThCtrlACC; HANDLE ThreadACC = CreateThread(NULL,0,ServerAccept,0,0,&DwThCtrlACC); return 0; } DWORD WINAPI ServerAccept(LPVOID) { int numconnect = 0; while(numconnect<MAXCONNECT) { int nm = sizeof(s_addr_out[numconnect]); socket[numconnect]= accept(sock,&s_addr_out[numconnect],&nm); numconnect++; } return 0; }
|
Второй способ основан на использовании расширения интерфейса Windows Sockets, предназначенного для выполнения асинхронных операций. Вместо того, чтобы ожидать соединение, приложение может вызвать один раз функцию WSAAsyncSelect, указав ей, что при получении запроса на установку соединения функция окна приложения должна получить сообщение:
#define WM_SOCKET (WM_USER + 1) //При попытке установки соединения главное окно приложения получит //сообщение WSA_ACCEPT rc = WSAAsyncSelect(srv_socket, hWnd, WM_SOCKET, FD_ACCEPT); if (rc > 0) { clossesocket(srv_socket); MessageBox(NULL, “WSAAsyncSelect Error”, “Error”,MB_OK); return; } |
В данном случае ожидание соединения выполняется для сокета srv_socket. Последний параметр функции имеет значение FD_ACCEPT. Это означает, что при попытке создания канала связи функция окна с идентификатором hWnd получит сообщение WSA_ACCEPT, определённое приложении.
Обработчик этого сообщения может выглядеть, например, следующим образом:
Void WndProc_OnWSAAccept(HWND hWnd, UNIT msg, WPARAM wParam, LPARAM lParam) { int rc; //При ошибке отменяем поступление извещений в главное //окно приложения if (WSAGETSELECTEDERROR(lParam) != 0) { MessageBox(NULL, “accept Error”, “Error”, MB_OK); WSAAsyncSelect(srv_socket, hwnd, 0, 0); return; } //определяем размер адреса сокета acc_sin_len = sizeof(acc_sin);
//разрешаем установку соединения srv_socket = accept(srv_socket, (LPSOCKADDR)&acc_sin, (int FAR *)&acc_sin_len);
if (srv_socket == INVALID_SOCKET) { MessageBox(NULL,“Invalid socket”,“Error”,MB_OK); return; } //если на данном сокете начинается передача данных от //клиента, в главное окно приложения поступит сообщение //WSA_NETEVENT. Это же сообшение поступит при //разрыве соединения. rc = WSAAsyncSelect(srv_socket, hWnd, WM_SOCKET, FD_READ | FD_CLOSE); if (rc > 0) { closesocket(srv_socket); MessageBox(NULL,“WSAAsyncSelect Error”,“Error”, MB_OK); return; } } |
В данном случае обработчик вызывает функцию accept, выполняющую создание канала передачи данных. После этого функция WSAAsyncSelect вызывается один раз для того, чтобы установить асинхронную обработку приёма данных от удалённого клиента, а также обработку ситуации разрыва канала связи.
Сторона клиента:
Для установки соединения со стороны клиента используется функция connect.
