poll에서 tcp, udp 두개 생성해서 쓰는 방법?
글쓴이: nayana / 작성시간: 금, 2005/02/04 - 5:57오후
#include <sys/time.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/poll.h> // 받아들일수 있는 클라이언트의 크기 #define OPEN_MAX 600 int main(int argc, char **argv) { int server_sockfd, client_sockfd, sockfd, udp_sock; int i, maxi; int nread; int state = 0; socklen_t clilen; struct sockaddr_in clientaddr, serveraddr, udpserveraddr; char buf[255]; struct pollfd client[OPEN_MAX]; if ((server_sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket error : "); exit(0); } if ( ( udp_sock = socket ( AF_INET, SOCK_DGRAM, 0 ) ) < 0 ) { perror( "udp socket error : " ); exit ( 0 ); } bzero(&serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); serveraddr.sin_port = htons(4444); bzero(&udpserveraddr, sizeof(udpserveraddr)); udpserveraddr.sin_family = AF_INET; udpserveraddr.sin_addr.s_addr = htonl(INADDR_ANY); udpserveraddr.sin_port = htons(5555); state = bind(server_sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)); if (state == -1) { perror("bind error : "); exit(0); } if ( bind( udp_sock, ( struct sockaddr *)&udpserveraddr, sizeof( udpserveraddr ) ) < 0 ) { perror( "udp bind error : " ); exit( 0 ); } state = listen(server_sockfd, 5); if (state == -1) { perror("listen error : "); exit(0); } // pollfd 구조체에 // 소켓지시자를 할당한다. // 소켓에 쓰기 events (POLLIN)에 대해서 // 반응하도록 세팅한다. client[0].fd = server_sockfd; client[0].events = POLLIN; // pollfd 구조체의 모든 fd 를 -1 로 초기화 한다. // fd 가 -1 이면 파일지시자가 세팅되어있지 않다는 뜻이다. for (i = 1; i < OPEN_MAX; i++) { client[i].fd = -1; } maxi = 0; // POLLING 시작 for (;;) { nread = poll(client, maxi + i, 1000); // 만약 POLLIN 이벤트에 대해서 // 되돌려준 이벤트가(revents) POLLIN // 이라면 accept 한다. if (client[0].revents & POLLIN) { clilen=sizeof(clientaddr); client_sockfd = accept(server_sockfd, (struct sockaddr *)&clientaddr, &clilen); for (i = 1; i < OPEN_MAX; i++) { if (client[i].fd < 0) { client[i].fd = client_sockfd; break; } } if (i == OPEN_MAX) { perror("too many clients : "); exit(0); } client[i].events = POLLIN; if (i > maxi) { maxi = i; } if (--nread <= 0) continue; } // 현재 파일지시자의 총갯수 만큼 루프를 돌면서 // 각 파일지시자에 POLLIN revent 가 발생했는지를 조사하고 // POLLIN이 발생했다면, 해당 파일지시자에서 데이타를 읽어들이고, // 주소정보를 돌려준다. // 만약 "quit" 를 읽었다면, 소켓연결을 끊는다. for (i = 1; i <= maxi; i++) { if ((sockfd = client[i].fd) < 0) continue; if (client[i].revents & (POLLIN | POLLERR)) { memset(buf, 0x00, 255); if (read(sockfd, buf, 255) <= 0) { close(client[i].fd); client[i].fd = -1; } else { if (strncmp(buf, "quit", 4) == 0) { write(sockfd, "byebye\n", 7); close(client[i].fd); client[i].fd = -1; break; } else { printf( "%s\n", buf ); } } } } } }
poll형태로 다중접속을 처리하려는 서버를 만들려고 합니다.
이 형태는 upd, tcp 를 다지원하는 형태로 서버를 만들려고 합니다. 책을 찾아보면 select로 udp, select형태의 예제가 많이 나와있는데...poll형태는 찾아볼수가 없습니다.
poll부분에서 udp는 어떻게 처리해야하나요?
Forums:
udp 소켓도..
listen 소켓처럼 POLLRDNORM 이벤트 설정해두고
revents & POLLRDNORM| POLLERR 이면
recvfrom()으로 읽어들이면 됩니다..
예전에 저렇게 구현해서 서비스했는데 별문제는 없었읍니다..
그리고, poll() 쓰실거라면 epoll()을 한번써보세요..
시스템 부하도 상당히 줄고, 어플리케이션 루프도 줄일수 있읍니다..
[code:1]listen 소켓처럼 POLLRDNORM 이벤트 설정해두고
일단 우선 POLLRDNORM 어떤 이벤트 인가요?
그리고 listen은 단지 state = listen(server_sockfd, 5);
이런식으로 했는데...답변이 잘이해가 안갑니다.^^;
poll 이벤트에 대해서는..
스티븐슨의 unix network programming volumn1 6장에 나와있읍니다.. 자세하다고는 할수없지만..
이벤트에 대해 정확히 알려면 모든 이벤트 셋팅해놓고 여러가지 경우를 테스트 해보는 수밖에 없읍니다..
POLLIN 은 POLLRDNORM | POLLRDBAND 입니다 ..
priority band data를 사용하지 않을거라면
POLLRDBAND 이벤트는 검사할필요가 없읍니다..
soket(udp_socket, .....);
bind(udp_socket, .....);
client[1].fd = udp_socket;
client[1].events = POLLRDNORM;
poll(client, .......);
if( client[1].revents & (POLLRDNORM | POLLERR))
recvfrom(upd_socket);
댓글 달기