select는 특정 이벤트가 발생하면 running을 하지만
poll은 계속해서 주기적으로 돌면서 이벤트를 체크한다.
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
1인자값 : 이벤트 등록 변수
2인자값 : 체크할 pollfd의 개수
3인자값 : time out 시간
만약에 poll(0, 0, 1000); 이렇게 하면
sleep(1); 과 같이 1초 delay를 줄 수 있다.
출처: http://forum.falinux.com/zbxe/?document_srl=405838
위의 페이지에 따르면
POLL함수는 확인하고 싶은 여러가지 이벤트를 미리 등록해놓고 그 이벤트들이 발생했는지
확인할 수 있는 편리한 방법을 제공한다.
POLL 함수의 PHASE는 5단계로 다음과 같다.
PHASE 1 : 주기적으로 check할 이벤트 등록
PHASE 2 : poll() 함수를 호출한다.
PHASE 3 : 이벤트가 발생하면 poll()함수 호출 후에 바로 return.
PHASE 4 : 이벤트가 발생하지 않으면, 이벤트 발생할 때까지 time-out 시간 만큼 기다린다.
PHASE 5 : 이벤트가 발생하면 해당 이벤트 배열 아이템의 값이 바뀌는데 이 값을 가지고 어느 이벤트가 발생했는지 알 수 있다.
< 서버쪽 예제> ... 클라이언트가 자꾸 제대로 안된다.. OTL..
코드출처 : http://stackoverflow.com/questions/448331/my-simple-poll-example-only-partially-works
-----------------------------------------------
#include#include #include #include #include "sys/time.h" #include "sys/types.h" #include #include #include "sys/socket.h" #include "netinet/in.h" #include "arpa/inet.h" #include #define PORT 29900 #define MAX_CONN 10 #define SECOND 1000 #define TIMEOUT (30 * SECOND) static int listen_socket(); int main(int argc, char **argv) { struct pollfd **my_fds; //array of pollfd structures for poll() struct pollfd *curr, *new_conn; //so I can loop through int num_fds; //count of how many are being used int i, j; //for loops char buff[255], buff2[255]; //for sending and recieving text struct sockaddr_in my_addr, their_addr; // my address information socklen_t sin_size; int buff_sz; //size of data recieved printf("App Started\n"); //allocate space for 10 my_fds = (struct pollfd**)calloc( MAX_CONN, sizeof(struct pollfd*)); //set all the pointers to NULL for (i = 0; i < MAX_CONN; i++) *(my_fds + i) = NULL; //I call listen_socket() which creates a socket to listen to //this is anchored into my_fds array at element 0. curr = (struct pollfd*) calloc (1, sizeof(struct pollfd)); curr->fd = listen_socket(); curr->events = POLLIN; curr->revents = 0; *my_fds = curr; printf("Listening socket fd locked always at position zero in array: %d\n", curr->fd); //num_fds, the count of items in the array is set to 1 //because the listen socket is already present num_fds = 1; //This is the main loop. //While (true) // set all struct pollfd items revents to 0 // call poll // loop through, see if there is data to read // read the data // loop through all sockets (except the listen_socket()) and send the data. while (1) { //reset all event flag for (i = 1; i < num_fds; i++) { curr = *(my_fds + i); curr->events = POLLIN | POLLPRI; printf("%i: fd %i\n", i, curr->fd); curr->revents = 0; send(curr->fd, "Enter some text:\n", 18, 0); } //put all this into poll and wait for something magical to happen printf("calling poll (%d sockets)\n", num_fds); if (poll(*my_fds, num_fds, TIMEOUT) == -1) { perror("poll"); exit(0); } printf("poll returned!\n"); //First item is the accepting socket....check it independently of the rest! curr = *my_fds; if (curr->revents != 0) { printf("We have a new connection.\nAccept goes here...\n"); //Accept the connection sin_size = sizeof their_addr; new_conn = (struct pollfd*) calloc(1, sizeof(struct pollfd)); new_conn->fd = accept(curr->fd, (struct sockaddr *)&their_addr, &sin_size); new_conn->events = POLLIN; new_conn->revents = 0; printf("Connection from %s\n", inet_ntoa(their_addr.sin_addr)); sprintf(buff, "Your %i\n", num_fds); send(new_conn->fd, buff, 255, 0); //Add it to the poll call *(my_fds + num_fds) = new_conn; num_fds++; } else { //skip first one, we know that's the accepting socket (handled above). for (i = 1; i < num_fds; i++) { curr = *(my_fds + i); if (curr->revents != 0) { buff_sz = recv(curr->fd, &buff, 255, 0); buff[buff_sz] = '\0'; printf("Recieved: %s", buff); //send the message to everyone else for (j = 1; j < num_fds; j++) { printf("i = %i, j = %i\n", i, j); if (j != i) { new_conn = *(my_fds + j); sprintf(buff2, "%i sent you %i: %s", i, j, buff); send(new_conn->fd, buff2, strlen(buff2) + 1, 0); } } } } } } printf("App Ended\n"); } static int listen_socket() { struct sockaddr_in a; int s; int yes; if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket"); return -1; } yes = 1; if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &yes, sizeof(yes)) < 0) { perror("setsockopt"); close(s); return -1; } memset(&a, 0, sizeof(a)); a.sin_port = htons(PORT); a.sin_family = AF_INET; if (bind(s, (struct sockaddr *) &a, sizeof(a)) < 0) { perror("bind"); close(s); return -1; } printf("Accepting connections on port %d\n", PORT); listen(s, 10); return s; }
-----------------------------------------------
도무지 이해가 안가서 일부분만 떼어왔다.
struct pollfd poll_events; // 체크할 event 정보를 갖는 struct
poll()을 사용하기 위한 변수를 선언.
poll_events 에는 감시 대상인 디스크립터와 어떤 event를 감시할지 결정해서 bit 값으로 지정.
int poll_state;
poll()이 수행한 결과값. 아래와 같은 반환값.
poll() 수행 후 반환 값 |
|
반환 값 |
설명 |
음수 |
반환 값이 음수라면 치명적인 에러가 발생한 것입니다. 한번 이렇게 음수로 에러가 발생하면 이후 계속 음수값이 날라 옵니다. 거의 대부분 프로그램을 다시 실행해야 됩니다. 반드시 체크해야 겠지요. |
0 |
지정한 대기시간, time-out이 지나도록 발생한 event가 없습니다. |
양수 |
event 가 발생했습니다.
|
poll_events.fd = fd;
감시 대상인 디스크립터를 지정.
poll_events.events = POLLIN | POLLERR; // 수신된 자료가 있는지, 에러가 있는지
체크하고 싶은 event에 대해 비트값으로 설정하여 지정.
poll_events.revents = 0;
revents를 0 으로 초기화.
poll_state = poll( // poll()을 호출하여 event 발생 여부 확인
(struct pollfd*)&poll_events, // event 등록 변수
1, // 체크할 pollfd 개수
1000 // time out 시간
);
체크할 event 정보를 넘겨 주고, 1은 체크할 pollfd 개수.
예제에는 감시하는 디스크립터가 한 개이지만 프로그램에 따라서는 여러 개의 디스크립터를 관리할 경우가 많음.
관리할 디스크립터가 많을 때, 각각을 변수로 처리하는 것 보다 배열로 처리하는 것이 편리.
이래서 poll() 이 편리.
poll()은 변수 하나 외에도 배열을 받을 수 있으며,
한번의 호출로 모든 event 발생 여부를 확인할 수 있어 매우 편리.
1000은 time-out 시간으로 발생한 event 가 없을 경우
poll()은 event가 발생할 때 까지 time-out 시간 동안 대기.
if ( 0 < poll_state)
poll() 함수 결과가 양수라면 event 가 발생.
if ( poll_events.revents & POLLIN)
발생한 event 중에 POLLIN 이 있는 지를 확인.
POLLIN에 해당되는 bit 가 1로 세트되어 있다면 POLLIN으로 AND한 값은 0 이 아닐 것.
이렇게 비트값을 확인하여 event 발생 여부를 확인.
cnt = read( fd, buf, 1024);
write( fd, buf, cnt);
자료 수신 event 가 발생했으므로 fd로부터 자료 값을 읽어 들이고,
예제 테스트를 위해 다시 그 자료를 전송.
'Language > C' 카테고리의 다른 글
writev 함수 예제 (472) | 2012.07.31 |
---|---|
readv 함수 예제 (480) | 2012.07.30 |
GCC 컴파일러 에러 메세지 리스트(Error Message List) (159) | 2012.07.24 |
select 함수 예제 (167) | 2012.07.23 |
Unix Domain Socket 예제 (165) | 2012.07.23 |