基於windows的使用select的I/O複用回顯伺服器端
阿新 • • 發佈:2018-11-06
使用過select函式可以將多個檔案描述符集中到一起監視,集中時也要按照監視項(接收、傳輸、異常)區分。
伺服器端:
#include <stdio.h> #include <stdlib.h> #include <WinSock2.h> #define BUF_SIZE 1024 void ErrorHandling(char* message); int main() { WSADATA wsa_data; SOCKET server_sock, client_sock; SOCKADDR_IN server_addr, client_addr; TIMEVAL time_out; fd_set reads, temp_reads;int addr_size; int str_len, fd_num; char buf[BUF_SIZE]; if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0) ErrorHandling("WSAStartup() error."); server_sock = socket(PF_INET, SOCK_STREAM, 0); if (server_sock == INVALID_SOCKET) ErrorHandling("socket() error."); memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(8000); if (bind(server_sock, (SOCKADDR*)&server_addr, sizeof(server_addr)) == SOCKET_ERROR) ErrorHandling("bind() error."); if (listen(server_sock, 5) == SOCKET_ERROR) ErrorHandling("listen() error."); FD_ZERO(&reads); FD_SET(server_sock, &reads); while (true) { temp_reads = reads; time_out.tv_sec = 5; time_out.tv_usec = 5000; if ((fd_num = select(0, &temp_reads, 0, 0, &time_out)) == SOCKET_ERROR) break; if (fd_num == 0) continue; for (int i = 0; i < reads.fd_count; ++i) { if (FD_ISSET(reads.fd_array[i], &temp_reads)) { if (reads.fd_array[i] == server_sock) // connection request { addr_size = sizeof(client_addr); client_sock = accept(server_sock, (SOCKADDR*)&client_addr, &addr_size); if (client_sock == INVALID_SOCKET) ErrorHandling("accept() error."); FD_SET(client_sock, &reads); printf("connected client: %d\n", client_sock); } else // read message { str_len = recv(reads.fd_array[i], buf, BUF_SIZE - 1, 0); if (str_len == 0) { FD_CLR(reads.fd_array[i], &reads); closesocket(temp_reads.fd_array[i]); printf("close client: %d\n", temp_reads.fd_array[i]); } else { send(reads.fd_array[i], buf, str_len, 0); // echo } } } } } closesocket(server_sock); WSACleanup(); return 0; } void ErrorHandling(char* message) { fputs(message, stderr); fputc('\n', stderr); exit(1); }
客戶端:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <WinSock2.h> #define BUF_SIZE 1024 void ErrorHandling(char* message); int main() { WSADATA wsa_data; SOCKET h_socket; SOCKADDR_IN server_addr; char message[BUF_SIZE]; int str_len; if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0) ErrorHandling("WSAStartup() error."); h_socket = socket(PF_INET, SOCK_STREAM, 0); if (h_socket == INVALID_SOCKET) ErrorHandling("socket() error."); memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); server_addr.sin_port = htons(8000); if (connect(h_socket, (SOCKADDR*)&server_addr, sizeof(server_addr)) == SOCKET_ERROR) ErrorHandling("connect() error."); else puts("Connect......"); while (true) { fputs("Insert message(q to quit): ", stdout); fgets(message, sizeof(message), stdin); if (!strcmp(message, "q\n") || !strcmp(message, "Q\n")) break; send(h_socket, message, strlen(message), 0); str_len = recv(h_socket, message, sizeof(message) - 1, 0); message[str_len] = 0; printf("Message from server: %s", message); } closesocket(h_socket); WSACleanup(); return 0; } void ErrorHandling(char* message) { fputs(message, stderr); fputc('\n', stderr); exit(1); }