select를 이용한 소켓 프로그래밍 질문하나만;;;
제가 서버쪽은 처음이다 보니 잘 모르는게 많습니다 ㅜㅜ
예전에 다른분이 작성한 코드 인데 당췌 이해가 가질 않아서요 ㅜㅜ
저 코드를 보면 select쪽에 이벤트가 발생하면 클라이언트 접속을 받고 스레드하나 만들고 스레드와 연결된 receiver함수에 접속한 클라이언트 소켓기술자를 넘겨서 해당 스레드가 알아서 데이타를 받도록 되어 있습니다
여기서 제가 궁금한건 굳이 select를 이용할 필요가 있느냐 입니다.
그냥 while(1) 안에서 accept이벤트가 발생하면 똑같이 스레드 할당하고 스레드와 연결된 함수에 소켓 기술자 넘겨서 알아서 데이타 받고 그러면 될것 같은데 왜 select를 썼는지 이해가 가질 않습니다
제가 select를 제대로 이해하지 못해서 그런건지 ㅜㅜㅜㅜㅜ
while(1)
{
FD_ZERO(&rset);
FD_SET(g_sockfd, &rset);
if (select(g_sockfd+1,&rset,(struct fd_set *)NULL,(struct fd_set *)NULL,&tval) == 0)
{ /* timeout */
continue;
}
else /* socket event */
{
if (!FD_ISSET(g_sockfd, &rset)) continue;
}
memset(&cli_addr, 0x00, sizeof(struct sockaddr_in));
clilen = sizeof(cli_addr);
accept_sd = 0;
accept_sd = accept(g_sockfd,(struct sockaddr *)&cli_addr, &clilen);
pthread_create(&threadID, NULL, receiver, (void *)accept_sd);
pthread_detach(threadID);
usleep(USLEEP_INTERVAL); /* 100000 */
}
select 를 이용하면 timeout 을 사용할 수 있습니다.
while 안에서 무한반복을 돌면서 이벤트를 기다려도 되지만, select 를 이용하면 timeout 시간동안 대기하거나, timeout 값을 안주면 무한 대기에 들어갑니다.
즉 불필요한 반복문의 실행을 줄일 수 있지요.
음...
음 스레드를 사용한다는것은 1:1이 아닌 1:다 관계를 생각하고 서버프로그램을 구현한것이겠죠?
하지만 accept_sd = accept(g_sockfd,(struct sockaddr *)&cli_addr, &clilen);
해서 accept_sd가지고 1:1통신은 되지만 새로운 연결이 왔으면 다시 accept하고 accept_sd는 덮어쓰겠죠?
그럼 처음 접속한 클라이언트랑의 통신은!?!?
select함수예제를 검색해보세요 ㅎ
accept_sd는 thread 인자로 넘어가는데요?
accept_sd가 전역변수로 다른 곳에서 사용하는 것이 아니라면
(pointer가 아니라) 값 그대로 넘어가는데, accept_sd를 굳이 위 loop 내에서 유지할 필요가 없어보입니다.
g_sockfd가 non-blocking이면
g_sockfd가 non-blocking이면 select()해서 확인 후 처리해야 할 것 같네요.
이 경우라면, select() -> accept() 사이에 connection이 사라질 수 있으니까 accept()에서 반환 값을 체크해야할 것 같구요.
g_sockfd가 non-blocking이 아니면 accept()가 blocking이 되니까 굳이 select()를 해줄 필요가 없어 보입니다.
(만약, 여러개 socket을 처리하거나, accept()할 것이 없을때 loop내에서 뭔가를 처리해야 한다면 select()가 필요한데...)
저도 서버쪽 구현은 무지한지라 man에서 확인한 것으로만 써 봅니다.
댓글 달기