fd_setをなめるのがめんどくさいなぁ。
#include <stdio.h> #include <winsock2.h> #include <time.h> #define _CRT_SECURE_DEPRECATE_MEMORY #include <memory.h> #define ECHO_PORT 7 #define MAX_BACKLOG 5 #define RCVBUFSIZE 256 #define die(...) do { fprintf(stderr, __VA_ARGS__); WSACleanup(); exit(1); } while(0) #define error(...) do { fprintf(stderr, __VA_ARGS__); } while(0) static void wsa_startup(WORD version, WSADATA *wsaData) { int n; if ((n = WSAStartup(version, wsaData)) != 0) { die("WASStartup(): %d\n", n); } if (version != wsaData->wVersion) { die("WASStartup(): WinSock version %d.%d not supported\n", LOWORD(version), HIWORD(version)); } } int echo(SOCKET sock) { char buf[RCVBUFSIZE + 1]; size_t len; if ((len = recv(sock, buf, RCVBUFSIZE, 0)) < 0) { error("recv(): %d\n", WSAGetLastError()); return -1; } if (len == 0) { return 0; } buf[len] = '\0'; error("recv(%d): %s", sock, buf); if (send(sock, buf, len, 0) < 0) { error("send(): %d\n", WSAGetLastError()); return -1; } return len; } int main() { int i; WSADATA wsaData; SOCKET sock; SOCKET ss[FD_SETSIZE]; struct sockaddr_in addr; fd_set fds; wsa_startup(MAKEWORD(2, 0), &wsaData); if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { die("socket(): %d\n", WSAGetLastError()); } addr.sin_family = AF_INET; addr.sin_port = htons(ECHO_PORT); addr.sin_addr.S_un.S_addr = INADDR_ANY; if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) != 0) { die("bind(): %d\n", WSAGetLastError()); } if (listen(sock, MAX_BACKLOG) != 0) { die("listen(): %d\n", WSAGetLastError()); } for (i = 0; i < FD_SETSIZE; i++) { ss[i] = INVALID_SOCKET; } ss[0] = sock; FD_ZERO(&fds); FD_SET(sock, &fds); while(1) { fd_set _fds; struct timeval timeout; memcpy(&_fds, &fds, sizeof(fd_set)); timeout.tv_sec = 1; timeout.tv_usec = 0; if (select(FD_SETSIZE, &_fds, NULL, NULL, &timeout) < 0) { die("select(): %d\n", WSAGetLastError()); } for (i = 0; i < FD_SETSIZE; i++) { int j; SOCKET fd = ss[i]; if (fd == INVALID_SOCKET || !FD_ISSET(fd, &_fds)) { continue; } if (sock == fd) { SOCKET s; struct sockaddr_in caddr; int len = sizeof(caddr); if ((s = accept(sock, (struct sockaddr *) &caddr, &len)) == INVALID_SOCKET) { die("accepr(): %d\n", WSAGetLastError()); } error("accepted.\n"); FD_SET(s, &fds); for (j = 0; j < FD_SETSIZE; j++) { if (ss[j] == INVALID_SOCKET) { ss[j] = s; break; } } if (j >= FD_SETSIZE) { closesocket(s); } } else { if (echo(fd) < 1) { FD_CLR(fd, &fds); for (j = 0; j < FD_SETSIZE; j++) { if (ss[j] == fd) { ss[j] = INVALID_SOCKET; break; } } closesocket(fd); } } } } WSACleanup(); return 0; }