반응형
#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;
}
반응형
'프로그래밍의 기초 > TCP | IP' 카테고리의 다른 글
readv & writev 입출력 함수 (0) | 2022.01.27 |
---|---|
send & recv 입출력 함수 (0) | 2022.01.24 |
select 함수의 이해와 서버의 구현 (0) | 2022.01.21 |
IO 멀티플렉싱 기반의 서버 (0) | 2022.01.21 |
프로세스간 통신의 적용 (0) | 2022.01.21 |