poll에서 tcp, udp 두개 생성해서 쓰는 방법?

nayana의 이미지

#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는 어떻게 처리해야하나요?

익명 사용자의 이미지

listen 소켓처럼 POLLRDNORM 이벤트 설정해두고

revents & POLLRDNORM| POLLERR 이면

recvfrom()으로 읽어들이면 됩니다..

예전에 저렇게 구현해서 서비스했는데 별문제는 없었읍니다..

그리고, poll() 쓰실거라면 epoll()을 한번써보세요..
시스템 부하도 상당히 줄고, 어플리케이션 루프도 줄일수 있읍니다..

nayana의 이미지

listen 소켓처럼 POLLRDNORM 이벤트 설정해두고 

revents & POLLRDNORM| POLLERR 이면 

recvfrom()으로 읽어들이면 됩니다.. 

예전에 저렇게 구현해서 서비스했는데 별문제는 없었읍니다.. 

그리고, poll() 쓰실거라면 epoll()을 한번써보세요.. 
시스템 부하도 상당히 줄고, 어플리케이션 루프도 줄일수 있읍니다

일단 우선 POLLRDNORM 어떤 이벤트 인가요?
그리고 listen은 단지 state = listen(server_sockfd, 5);
이런식으로 했는데...답변이 잘이해가 안갑니다.^^;

익명 사용자의 이미지

스티븐슨의 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);

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.