반응형
#include <winsock2.h>
int WSAAPI select(
  [in]      int           nfds,
  [in, out] fd_set        *readfds,
  [in, out] fd_set        *writefds,
  [in, out] fd_set        *exceptfds,
  [in]      const timeval *timeout
);
→ 성공 시 0 이상, 실패 시 -1 반환
typedef struct timeval {
  long tv_sec;
  long tv_usec;
} TIMEVAL, *PTIMEVAL, *LPTIMEVAL;

- window의 fd_set은 Linux와 같이 비트의 배열로 구성되어 있지 않음

typedef struct fd_set {
  u_int  fd_count;
  SOCKET fd_array[FD_SETSIZE];
} fd_set, FD_SET, *PFD_SET, *LPFD_SET;

- fd_count: 저장된 socket의 handle의 수를 기록

- fd_array: socket의 handle 저장

 

- Linux의 file descriptor는 0에서부터 시작하여 하나씩 값이 증가하는 구조를 지나므로 현재 생성된 file descriptor의 수와 마지막으로 생성된 file descriptor의 수 사이에 관계성을 찾을 수 있음

- window 기반의 socket handle은 0에서부터 시작하지 않고 생성되는 handle의 정수 값 사이의 규칙을 찾을 수 없음 (따라서 socket handle을 저장하는 배열, 저장된 배열의 수를 기록하기 위한 변수 필요)

 

  • 윈도우 기반 멀티플렉싱 서버의 구현
// multiplexing server
#define		BUF_SZ		30
int main(int argc, char* argv[])
{
	WSADATA wsaData;
	int serv_sock, clnt_sock;
	SOCKADDR_IN serv_addr, clnt_addr;
	fd_set reads, temps;
	TIMEVAL timeout;
	int num, result, sz, len;
	char buf[BUF_SZ];

	if (argc != 2)
	{
		printf("usage: %s <addr>\n", argv[0]);
		exit(1);
	}

	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
		err_handling("startup() error");

	serv_sock = socket(PF_INET, SOCK_STREAM, 0);
	if (serv_sock == INVALID_SOCKET)
		err_handling("socket() error");

	memset(&serv_addr, 0, sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	serv_addr.sin_port = htons(atoi(argv[1]));

	if(bind(serv_sock, &serv_addr, sizeof(serv_addr))== SOCKET_ERROR)
		err_handling("bind() error");

	if (listen(serv_sock, 5) == SOCKET_ERROR)
		err_handling("listen() error");

	FD_ZERO(&reads);
	FD_SET(serv_sock, &reads);
	num = serv_sock + 1;
	while (1)
	{
		temps = reads;
		timeout.tv_sec = 5;
		timeout.tv_usec = 5000;

		result = select(num, &temps, 0, 0, &timeout);

		if (result == SOCKET_ERROR)
			break;

		else if (result == 0)
			continue;

		for (int i = 0; i < reads.fd_count; i++)
		{
			if (FD_ISSET(reads.fd_array[i], &temps))
			{
				if (reads.fd_array[i] == serv_sock)
				{
					sz = sizeof(clnt_addr);
					clnt_sock = accept(serv_sock, &clnt_addr, &sz);
					FD_SET(clnt_sock, &reads);
					printf("connect: %d\n", clnt_sock);
				}
				else
				{
					len = recv(reads.fd_array[i], buf, BUF_SZ, 0);
					if (len == 0)
					{
						FD_CLR(reads.fd_array[i], &reads);
						closesocket(temps.fd_array[i]);
						printf("disconnect: %d\n", temps.fd_array[i]);
					}
					else
						send(reads.fd_array[i], buf, len, 0);
				}
			}
		}
	}
	closesocket(serv_sock);
	WSACleanup();
	return 0;
}​
반응형

+ Recent posts