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;
}


-----------------------------------------------


도무지 이해가 안가서 일부분만 떼어왔다.

http://forum.falinux.com/zbxe/?document_srl=405838

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

+ Recent posts