epoll에서 event catch가 정상적이지 않습니다..

dreampia의 이미지

solaris에서 select()로 소켓 다중화를 구현했습니다.
사용하는 solaris의 경우 해당 프로세스에서 FD_SETSIZE를 define하면 select()도 1024이상 처리가 가능하고
실제로 그렇게 하고 있습니다.

리눅스로 마이그레이션을 하니 select()에서 문제가 발생하더군요..
1024이상은 커널을 재컴파일해야 한다는데 할 수 없는 환경입니다..

그래서 epoll을 선택해서 select()부분만 epoll로 변경하고 처리했는데.. 잘 안되네요

구조상 NON-BLOCK 소켓이어야 해서 epoll의 ET를 사용합니다..

맨 아래와 같은 code로 서버를 작성했습니다.
가상 client를 만들어서 script로 동시에 20-100개씩 sleep 1; 정도를 주면서 붙이면
select()로 만들어진 것은 1000정도까지 붙여도 아무 문제 없이 잘 연결되고 데이터를 받는데(sleep을 거의 주지 않아도..)
epoll은 모든 연결을 감지 못하고 일부 몇개가 누락이 됩니다..
epoll로 몇개의 연결이 누락된 상태에서 정상적인 client로 붙이면 tcp 연결은 되는데 현재 붙은 사용자의 데이터를 받지 못하고
이전에 script로 처리했을때 누락된 데이터를 한건씩 수신합니다..

이상한것은 netstat -an | grep 포트 | grep EST | wc -l 하면 1000개가 정확하게 나옵니다
NON-BLOCK부분을 모두 막고 LT모드로 해도 1000개의 데이터를 다 수신 못 하는데요...

어떤 부분을 확인해봐야 할까요?
가상client연결시 1초에 한개씩 천천히 연결하면 문제없이 잘 연결됩니다..
원하는건 동시에 여러개가 연결됐을때도 아무 문제가 없어야 한다는 것입니다..

socket에서 읽는 부분은 아래와 같이 loop를 돌면서 원하는 데이터를 다 읽을떄까지 기다립니다

    while (restbyte)
    {
        if ((ret = recv(sockfd, ptr+HSIZE+accum, restbyte, MSG_WAITALL)) <= 0)
            return(ret);
 
        accum += ret;
        restbyte -= ret;
    }

실제 가동되는 main의 대강 소스 모습입니다..
중간 중간에 함수가 많아서 소스 전체를 copy하지 않았습니다.

#define FD_SETSIZE      4096
 
 
int main()
{
    tcp socket listen; 
    set non-block;
    domain socket listen;
    set non-block;
 
    events = (struct epoll_event *) malloc(sizeof(*events) * FD_SETSIZE);
    if (! (epfd = epoll_create(FD_SETSIZE)))
    {
        printf(">> epoll create error (%s)\n", strerror(errno));
        endproc(-1);
    }
 
    EpollCtl(tcp socket, EPOLLIN | EPOLLET);
    EpollCtl(domain socket, EPOLLIN | EPOLLET);
 
    for ( ; ; )
    {
        // timeout:-1 무한대기, 양수:msec sleep
        ret = epoll_wait(epfd, events, FD_SETSIZE, -1);
 
        for (i = 0; i < ret; i++)
        {
            if (events[i].data.fd == tcp socket || events[i].data.fd == domain socket)
            {
                accept;
                set non-block;
                set tcp-nodelay;
                EpollCtl(newfd, EPOLLIN | EPOLLET);
            }
            else
            {
                read data from client socket...
            }
        }
    }
}
 
int EpollCtl(int sockfd, uint32_t mode)
{
    struct  epoll_event ev;
 
 
    bzero(&ev, sizeof(ev));
    ev.events = mode;
    ev.data.fd = sockfd;
 
    if (epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &ev) < 0)
    {
        printf(">> epoll ctl error (%s)\n", strerror(errno));
        return(ERROR);
    }
    return(GOOD);
}

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.