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);
댓글 달기