首页 > 学技术 > 技术网文 > C/C++ > 正文

[精华] epoll模型的使用及其描述符耗尽问题的探讨


来源 chinaunix.net kuqin整理

每次接受新连接的时候,我监视了这几个事件。

EPOLLIN | EPOLLET |  EPOLLERR | EPOLLHUP | EPOLLPRI;

每次有一批事件返回,经过统计  
返回的一批fd数量=出错关闭的fd数量+由EPOLLIN转为EPOLLOUT的fd数量+EPOLLOUT正常处理关闭的fd的数量。 也就是说,每批事件都完全处理,没有遗漏。

观察发现EPOLLET |  EPOLLERR | EPOLLHUP 这3发事件的发生率为0。

但fd却成增大趋势。以前那写较小的fd在经历一段时间后渐渐丢失,不再可用。

请问fd都丢失到哪里去了?

[ 本帖最后由 wyezl 于 2006-8-25 10:17 编辑 ]



 思一克 回复于:2006-08-18 10:46:50

有程序?


 wyezl 回复于:2006-08-18 11:10:12




/*-------------------------------------------------------------------------------------------------
gcc -o httpd httpd.c -lpthread 
author: wyezl
2006.4.28
---------------------------------------------------------------------------------------------------*/

#include <sys/socket.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <errno.h>

#define PORT 8888
#define MAXFDS 5000
#define EVENTSIZE 100

#define BUFFER "HTTP/1.1 200 OK\r\nContent-Length: 5\r\nConnection: close\r\nContent-Type: text/html\r\n\r\nHello"

int epfd;
void *serv_epoll(void *p);
void setnonblocking(int fd)
{
    int opts;
    opts=fcntl(fd, F_GETFL);
    if (opts < 0)
    {
          fprintf(stderr, "fcntl failed\n");
          return;
    }
    opts = opts | O_NONBLOCK;
    if(fcntl(fd, F_SETFL, opts) < 0)
    {
          fprintf(stderr, "fcntl failed\n");
          return;
    }
    return;
}

int main(int argc, char *argv[])
{
    int fd, cfd,opt=1;
    struct epoll_event ev;
    struct sockaddr_in sin, cin;
    socklen_t sin_len = sizeof(struct sockaddr_in);
    pthread_t tid;
    pthread_attr_t attr;

    epfd = epoll_create(MAXFDS);
    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) <= 0)
    {
          fprintf(stderr, "socket failed\n");
          return -1;
    }
    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*)&opt, sizeof(opt));

    memset(&sin, 0, sizeof(struct sockaddr_in));
    sin.sin_family = AF_INET;
    sin.sin_port = htons((short)(PORT));
    sin.sin_addr.s_addr = INADDR_ANY;
    if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)) != 0)
    {
          fprintf(stderr, "bind failed\n");
          return -1;
    }
    if (listen(fd, 32) != 0)
    {
          fprintf(stderr, "listen failed\n");
          return -1;
    }

    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
    if (pthread_create(&tid, &attr, serv_epoll, NULL) != 0)
    {
          fprintf(stderr, "pthread_create failed\n");
          return -1;
    }

    while ((cfd = accept(fd, (struct sockaddr *)&cin, &sin_len)) > 0)
    {
          setnonblocking(cfd);
          ev.data.fd = cfd;
          ev.events = EPOLLIN | EPOLLET |  EPOLLERR | EPOLLHUP | EPOLLPRI;
          epoll_ctl(epfd, EPOLL_CTL_ADD, cfd, &ev);
          //printf("connect from %s\n",inet_ntoa(cin.sin_addr));
          //printf("cfd=%d\n",cfd);
    }

    if (fd > 0)
          close(fd);
    return 0;
}

void *serv_epoll(void *p)
{
    int i, ret, cfd, nfds;;
    struct epoll_event ev,events[EVENTSIZE];
    char buffer[512];

    while (1)
    {
          nfds = epoll_wait(epfd, events, EVENTSIZE , -1);
          //printf("nfds ........... %d\n",nfds);
          for (i=0; i<nfds; i++)
          {
                if(events.events & EPOLLIN)
                {
                    cfd = events.data.fd;
                    ret = recv(cfd, buffer, sizeof(buffer),0);
                    //printf("read ret..........= %d\n",ret);

                    ev.data.fd = cfd;
                    ev.events = EPOLLOUT | EPOLLET;
                    epoll_ctl(epfd, EPOLL_CTL_MOD, cfd, &ev);
                }
                else if(events.events & EPOLLOUT)
                {
                    cfd = events.data.fd;
                    ret = send(cfd, BUFFER, strlen(BUFFER), 0);
                    //printf("send ret...........= %d\n", ret);

                    ev.data.fd = cfd;
                    epoll_ctl(epfd, EPOLL_CTL_DEL, cfd, &ev);
                  
                    close(cfd);

                }

                   else
      {

cfd = events.data.fd;
ev.data.fd = cfd;
epoll_ctl(epfd, EPOLL_CTL_DEL, cfd, &ev);
close(cfd);
       }


          }
    }
    return NULL;
}















 wyezl 回复于:2006-08-18 11:23:46

只要能帮我找出描述符从哪耗尽的就行。
:)


 思一克 回复于:2006-08-18 11:50:07

是不是main()中的cfd没有关闭


 wyezl 回复于:2006-08-18 12:25:12

main中只接受连接,加入监视,不做处理。
估计epoll_ctl 没判断出错,我下午再测试一下。


 wyezl 回复于:2006-08-18 13:27:07

if(epoll_ctl(epfd, EPOLL_CTL_ADD, cfd, &ev)<0)
                        printf("............................................EPOLL_CTL_ADD error!\n");

if(epoll_ctl(epfd, EPOLL_CTL_MOD, cfd, &ev)<0)
                                                printf(".......................................EPOLL_CTL_MOD error!\n");


修改了两句,但未发现这里的错误输出,估计也不是这的问题。

不知道到底从哪耗尽的,奇怪。


 wyezl 回复于:2006-08-18 15:50:15

继续顶。。。。。。。。。。。。。。。。


 思一克 回复于:2006-08-18 15:58:14

想帮你实验,但程序无法编译


 playmud 回复于:2006-08-19 20:48:39

挑挑错吧,说的不对的话,请见谅!
1,    while ((cfd = accept(fd, (struct sockaddr *)&cin, &sin_len)) > 0)
    可够改成
while(1)
cfd = accept(fd, (struct sockaddr *)&cin, &sin_len;
if(cfd>0)
..
2,你是要让客户端发送一次就不再发送了吗?
                if(events.events & EPOLLIN)

                {
                    cfd = events.data.fd;
                    ret = recv(cfd, buffer, sizeof(buffer),0);
                    //printf("read ret..........= %d\n",ret);

                    ev.data.fd = cfd;
                    ev.events = EPOLLOUT | EPOLLET;
                    epoll_ctl(epfd, EPOLL_CTL_MOD, cfd, &ev);
                }

3,将accept事件列入epoll监控的对象
4,对close最好做一个判断


 tysn 回复于:2006-08-20 11:25:26

accept()之后的epoll_ctl(epfd, EPOLL_CTL_ADD, cfd, &ev);
要改成:if (epoll_ctl(epfd, EPOLL_CTL_ADD, cfd, &ev)<0) close(cfd);
估计就是这里错吧,这几率比较小,
所以出现“fd在经历一段时间后渐渐丢失”

另外还要考虑playmud挑的4点问题,
比如第一点,lz那样写的while好像跟if差不多,
accept也是在很小几率下出错,出错之后程序就退出?

说的不对的话,请指正!


 wyezl 回复于:2006-08-20 12:58:20

引用:原帖由 思一克 于 2006-8-18 15:58 发表
想帮你实验,但程序无法编译 



编译没问题,需要linux 2。6以上内核的支持。


 wyezl 回复于:2006-08-20 13:10:17

引用:



挑挑错吧,说的不对的话,请见谅!
1,    while ((cfd = accept(fd, (struct sockaddr *)&cin, &sin_len)) > 0)
    可够改成
while(1)
cfd = accept(fd, (struct sockaddr *)&cin, &sin_len;
if(cfd>0)
..
2,你是要让客户端发送一次就不再发送了吗?


CODE:[Copy to clipboard]                if(events.events & EPOLLIN)
                {
                    cfd = events[ i ].data.fd;
                    ret = recv(cfd, buffer, sizeof(buffer),0);
                    //printf("read ret..........= %d\n",ret);

                    ev.data.fd = cfd;
                    ev.events = EPOLLOUT | EPOLLET;
                    epoll_ctl(epfd, EPOLL_CTL_MOD, cfd, &ev);
                }
3,将accept事件列入epoll监控的对象
4,对close最好做一个判断 





... 



1,如果描述符已经耗尽,这样判断cfd永远不会成立。所以就让它退出算了。

2,我只取http请求的头信息的第一行。 get  /xxx  http/1.0 做简单分析,其他的都不要了。按照tcp协议的特点,本应该多次读取的,但测试发现,只读一次就能得到我想要的,基本上没出过错。
里面的数据没读完就留那了,会不会对以后的请求造成什么不好的影响?


3,accept是在住线程里跑,加入了epoll有什么好处吗?

4,对close没做判断,这点确实是遗漏了。我得补上。
谢谢你的建议。

[ 本帖最后由 wyezl 于 2006-8-20 13:16 编辑 ]


 wyezl 回复于:2006-08-20 13:14:43

引用:原帖由 tysn 于 2006-8-20 11:25 发表
accept()之后的epoll_ctl(epfd, EPOLL_CTL_ADD, cfd, &ev);
要改成:if (epoll_ctl(epfd, EPOLL_CTL_ADD, cfd, &ev)<0) close(cfd);
估计就是这里错吧,这几率比较小,
所以出现“fd在经历一段时间 ... 



这一条判断我后来添加了。 但这儿出错几率几乎为0 。


现在仍未发现耗尽的原因。怀疑是不是epoll机制本身有问题呢?


 wyezl 回复于:2006-08-21 09:41:20

继续顶。。。。。。。。。


 思一克 回复于:2006-08-21 09:49:38

EPOLLIN事件后是不是应该关闭CFD?

我看的,不一定准确,因为无法实验你的程序


 wyezl 回复于:2006-08-21 12:14:14

引用:原帖由 思一克 于 2006-8-21 09:49 发表
EPOLLIN事件后是不是应该关闭CFD?

我看的,不一定准确,因为无法实验你的程序 



如果关闭了,以后就不会有EPOLLOUT了。 因为我是接受请求,然后返回所请求的信息。


 思一克 回复于:2006-08-21 12:18:40

那你把能编译的贴出,我帮你实验。如果你愿意的话


 billzhou 回复于:2006-08-21 12:34:25

不懂  什么是epoll,哪位兄弟给解释一下


 wyezl 回复于:2006-08-21 16:47:23

引用:原帖由 思一克 于 2006-8-21 12:18 发表
那你把能编译的贴出,我帮你实验。如果你愿意的话 



我贴出的代码就是能编译的。
请问你用的是什么操作系统? 版本?
这个程序只能在linux上运行,而且内核版本必须在2.6以上。

[ 本帖最后由 wyezl 于 2006-8-21 16:52 编辑 ]


 wyezl 回复于:2006-08-21 16:49:00

思一克是个热心的斑竹,先赞一个。 :)


 精简指令 回复于:2006-08-21 20:12:49

“但fd却成增大趋势。以前那写较小的fd在经历一段时间后渐渐丢失,不再可用。”

是否已经将FD用光了? 如果没有用光,试着用到最大值,看看是否会重新分配较小的FD


 safedead 回复于:2006-08-21 21:52:01

我没有这么用过epoll

我的程序是仅用epoll弹出发生EPOLIN事件的LISTEN套接字
然后就ACCEPT出客户端连接就交给线程处理了
没有发生过fd耗尽的情况


 思一克 回复于:2006-08-22 08:19:12

to LZ,

你的模型好象不太对,至少不太好。epoll_wait和ACCEPT的次序?

你在网络上找,有现成的好的。


 wyezl 回复于:2006-08-22 09:54:56

引用:原帖由 safedead 于 2006-8-21 21:52 发表
我没有这么用过epoll

我的程序是仅用epoll弹出发生EPOLIN事件的LISTEN套接字
然后就ACCEPT出客户端连接就交给线程处理了
没有发生过fd耗尽的情况 



方便把你的模型大概贴出来看一下吗?


 wyezl 回复于:2006-08-22 09:55:54

引用:原帖由 精简指令 于 2006-8-21 20:12 发表
“但fd却成增大趋势。以前那写较小的fd在经历一段时间后渐渐丢失,不再可用。”

是否已经将FD用光了? 如果没有用光,试着用到最大值,看看是否会重新分配较小的FD 



确实用光了。不能分配小的了。


 星之孩子 回复于:2006-08-22 10:06:27

为何你用epoll还要用多线程
感觉你这个模型怪怪的


 wyezl 回复于:2006-08-22 10:32:07

只开了两个线程。 epoll独占一个。


 星之孩子 回复于:2006-08-22 10:34:49

多个线程这样用epoll不知道会不会有问题
其实你的应用根本不用多线程


 wyezl 回复于:2006-08-22 11:05:13

引用:原帖由 思一克 于 2006-8-22 08:19 发表
to LZ,

你的模型好象不太对,至少不太好。epoll_wait和ACCEPT的次序?

你在网络上找,有现成的好的。 



能把你觉得好的模型共享一下吗?


 nuclearweapon 回复于:2006-08-22 11:43:27

刚才测试了lz的程序。
50个并发,cfd最大达到37然后回落到5。

如上测试多次没有发现cfd有增大的趋势。
所以感觉和内核版本有关系。

测试环境:

kernel 2.6.15
gcc 4.0.3

distribution:ubuntu


 wyezl 回复于:2006-08-22 11:47:58

下面这个模型我也用过。不过效率很底。


#include <iostream>

#include <sys/socket.h>

#include <sys/epoll.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <fcntl.h>

#include <unistd.h>

#include <stdio.h>



#define MAXLINE 10

#define OPEN_MAX 100

#define LISTENQ 20

#define SERV_PORT 5555

#define INFTIM 1000



void setnonblocking(int sock)

{

  int opts;

  opts=fcntl(sock,F_GETFL);

  if(opts<0)

  {

      perror("fcntl(sock,GETFL)");

      exit(1);

  }

  opts = opts|O_NONBLOCK;

  if(fcntl(sock,F_SETFL,opts)<0)

  {

      perror("fcntl(sock,SETFL,opts)");

      exit(1);

  }   

}



int main()

{

  int i, maxi, listenfd, connfd, sockfd,epfd,nfds;

  ssize_t n;

  char line[MAXLINE];

  socklen_t clilen;

  //声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件

  struct epoll_event ev,events[20];

  //生成用于处理accept的epoll专用的文件描述符

  epfd=epoll_create(256);



  struct sockaddr_in clientaddr;

  struct sockaddr_in serveraddr;

  listenfd = socket(AF_INET, SOCK_STREAM, 0);

  //把socket设置为非阻塞方式

  setnonblocking(listenfd);

  //设置与要处理的事件相关的文件描述符

  ev.data.fd=listenfd;

  //设置要处理的事件类型

  ev.events=EPOLLIN|EPOLLET;

  //注册epoll事件

  epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);



  bzero(&serveraddr, sizeof(serveraddr));

  serveraddr.sin_family = AF_INET;



  char *local_addr="200.200.200.204";

  inet_aton(local_addr,&(serveraddr.sin_addr));//htons(SERV_PORT);

  serveraddr.sin_port=htons(SERV_PORT);

  bind(listenfd,(sockaddr *)&serveraddr, sizeof(serveraddr));

  listen(listenfd, LISTENQ);



  maxi = 0; 

  for ( ; ; ) {

      //等待epoll事件的发生

      nfds=epoll_wait(epfd,events,20,500);

      //处理所发生的所有事件     

      for(i=0;i<nfds;++i)

      {

          if(events.data.fd==listenfd)

          {



            connfd = accept(listenfd,(sockaddr *)&clientaddr, &clilen);

            if(connfd<0){

                perror("connfd<0");

                exit(1);

            }

            setnonblocking(connfd);



            char *str = inet_ntoa(clientaddr.sin_addr);

            std::cout<<"connect from "<_u115 ?tr<<std::endl;

            //设置用于读操作的文件描述符

            ev.data.fd=connfd;

            //设置用于注测的读操作事件

            ev.events=EPOLLIN|EPOLLET;

            //注册ev

            epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);

          }

          else if(events.events&EPOLLIN)

          {

            if ( (sockfd = events.data.fd) < 0) continue;

            if ( (n = read(sockfd, line, MAXLINE)) < 0) {

                if (errno == ECONNRESET) {



                    close(sockfd);

                    events.data.fd = -1;

                } else 

                    std::cout<<"readline error"<<std::endl;

            } else if (n == 0) {

                close(sockfd);

                events.data.fd = -1;

            }

            //设置用于写操作的文件描述符

            ev.data.fd=sockfd;

            //设置用于注测的写操作事件

            ev.events=EPOLLOUT|EPOLLET;

            //修改sockfd上要处理的事件为EPOLLOUT

            epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);

          }

          else if(events.events&EPOLLOUT)

          {   

            sockfd = events.data.fd;

            write(sockfd, line, n);

            //设置用于读操作的文件描述符

            ev.data.fd=sockfd;

            //设置用于注测的读操作事件

            ev.events=EPOLLIN|EPOLLET;

            //修改sockfd上要处理的事件为EPOLIN

            epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);

          }



      }



  }

}


 wyezl 回复于:2006-08-22 11:50:49

引用:原帖由 nuclearweapon 于 2006-8-22 11:43 发表
刚才测试了lz的程序。
50个并发,cfd最大达到37然后回落到5。

如上测试多次没有发现cfd有增大的趋势。
所以感觉和内核版本有关系。

测试环境:

kernel 2.6.15
gcc 4.0.3

distribution:ubuntu 



50个并发,cfd最大达到37然后回落到5。 是有这样的现象。所以我说是增大趋势。而没有说直线增长。

这也不是你几分钟就能测试出来的。1024个fd也需要一个多小时才能耗尽(大约处理100万请求)。而且是量比较大的线上测试。


 nuclearweapon 回复于:2006-08-22 11:57:36

引用:原帖由 wyezl 于 2006-8-22 11:50 发表


50个并发,cfd最大达到37然后回落到5。 是有这样的现象。所以我说是增大趋势。而没有说直线增长。

这也不是你几分钟就能测试出来的。1024个fd也需要一个多小时才能耗尽(大约处理100万请求)。而且是量比较 ... 



你这里说的耗尽是什么意思?

表示Accept不能再接受client了吗?


 nuclearweapon 回复于:2006-08-22 12:02:51

就调试来说,当服务程序挂起的时候
你可以看如下目录:
/proc/your_process_id/fd

看一看有那些fd在被你的进程使用!


 星之孩子 回复于:2006-08-22 12:38:41

你另外一个模型就是epoll例子的模型吧
凭什么说人家的就效率低了?


 wyezl 回复于:2006-08-22 13:10:18

引用:原帖由 星之孩子 于 2006-8-22 12:38 发表
你另外一个模型就是epoll例子的模型吧
凭什么说人家的就效率低了? 




我测试过。处理能力底了20%。


 思一克 回复于:2006-08-22 13:11:53

to LZ,

你做什么服务? 有多少同时连接?


 wyezl 回复于:2006-08-22 13:18:46

引用:原帖由 nuclearweapon 于 2006-8-22 12:02 发表
就调试来说,当服务程序挂起的时候
你可以看如下目录:
/proc/your_process_id/fd

看一看有那些fd在被你的进程使用! 



我一共监视了5000个描述符,程序跑了一天,基本上快耗完了。还剩不到1000个了。


ls /proc/24152/fd/
Display all 4051 possibilities? (y or n)

可见这些耗尽的描述符都在使用中。 但不知道什么地方没把它们释放。


 wyezl 回复于:2006-08-22 13:22:36

引用:原帖由 思一克 于 2006-8-22 13:11 发表
to LZ,

你做什么服务? 有多少同时连接? 



http服务。简单的数据。基本上是读取内存的操作。类似股票行情数据。

当然每秒能处理越多请求越好。


 playmud 回复于:2006-08-22 13:48:27

5000 个?我怎么看你的listen才32?
    if (listen(fd, 32) != 0)
    {
          fprintf(stderr, "listen failed\n");
          return -1;
    }

SYNOPSIS

       #include <sys/socket.h>

       int listen(int sockfd, int backlog);

DESCRIPTION
       To  accept connections, a socket is first created with socket(2), a willingness to accept incoming connec-
       tions and a queue limit for incoming connections are specified with listen(), and then the connections are
       accepted with accept(2).  The listen() call applies only to sockets of type SOCK_STREAM or SOCK_SEQPACKET.

       The backlog parameter defines the maximum length the queue of pending connections may grow to.  If a  con-
       nection request arrives with the queue full the client may receive an error with an indication of ECONNRE-
       FUSED or, if the underlying protocol supports retransmission, the request may be ignored so  that  retries
       succeed.



 思一克 回复于:2006-08-22 14:07:38

你的程序我看了。好象是有漏洞,而且是必须在大量连接,慢速的断线才可疑的。

一个fd有事件EPOLLIN后,如果断线,EPOLLOUT永不再来,你的fd不就永远不被关闭了吗?

请讨论。


 slay78 回复于:2006-08-22 14:13:42

引用:原帖由 playmud 于 2006-8-22 13:48 发表
5000 个?我怎么看你的listen才32?
    if (listen(fd, 32) != 0)
    {
          fprintf(stderr, "listen failed\n");
          return -1;
    }

SYNOPSIS

       #include <s ... 



人家这个32不是表示可以连32个的意思,这个32表示最多有32个同时在连并且都没连上,第33个进不来而已


 思一克 回复于:2006-08-22 14:14:15

虽然有HUP等else 控制。但如果EPOLLIN之后由于网络的不好状况,其它时间不在来?如何


 wyezl 回复于:2006-08-22 14:32:13

引用:原帖由 playmud 于 2006-8-22 13:48 发表
5000 个?我怎么看你的listen才32?
    if (listen(fd, 32) != 0)
    {
          fprintf(stderr, "listen failed\n");
          return -1;
    }

SYNOPSIS

       #include <s ... 




这个32与5000个同时在线并不矛盾。 

又不是说1秒内把这5000个连线全接受进来。
5000是我的epoll所监视的最大描述符个数。


 nuclearweapon 回复于:2006-08-22 14:33:08

引用:原帖由 思一克 于 2006-8-22 14:14 发表
一个fd有事件EPOLLIN后,如果断线,EPOLLOUT永不再来,你的fd不就永远不被关闭了吗?



由于有SO_KEEPALIVE可以避免这种情况吧(lz的程序也做了处理)。
否则就是client有问题,一直连着不放。


 nuclearweapon 回复于:2006-08-22 14:34:54

引用:原帖由 wyezl 于 2006-8-22 13:18 发表


我一共监视了5000个描述符,程序跑了一天,基本上快耗完了。还剩不到1000个了。


ls /proc/24152/fd/
Display all 4051 possibilities? (y or n)

可见这些耗尽的描述符都在使用中。 但不知道什么地方 ... 



用ls -l 看下是那些socket 
再用 netstat -a看下这些socket的状态


 wyezl 回复于:2006-08-22 14:38:09

引用:原帖由 思一克 于 2006-8-22 14:07 发表
你的程序我看了。好象是有漏洞,而且是必须在大量连接,慢速的断线才可疑的。
 




就是漫漫耗尽的。

第二种模型也一样。出现这样耗尽的情况。 以前都是用测试工具测试的,基本上看不出破绽。
在线上测试,就很明显了。。


 思一克 回复于:2006-08-22 14:41:07

to wyezl,

FD泄露,原因就是没有close是无疑问的。
WHY MEIYOU close?
就是事件有的时候(比如网络坏等原因)没有到来。


 wyezl 回复于:2006-08-22 14:51:33

引用:原帖由 nuclearweapon 于 2006-8-22 14:34 发表


用ls -l 看下是那些socket 
再用 netstat -a看下这些socket的状态 




这是只监视1024个fds的时候的部分贴图。

# netstat -a
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address               Foreign Address             State      
tcp        0      0 *:32768                     *:*                         LISTEN      
tcp        0      0 *:sunrpc                    *:*                         LISTEN      
tcp        0      0 *:http                      *:*                         LISTEN      
tcp        0      0 xxx.108.37.77:http          122.48.0.37:56652           SYN_RECV    
tcp        0      0 xxx.108.37.77:http          211.147.253.74:55689        SYN_RECV    
tcp        0      0 xxx.108.37.77:http          219.135.251.110:2669        SYN_RECV    
warning, got duplicate tcp line.
tcp        0      0 xxx.108.37.77:http          122.48.0.89:12881           SYN_RECV    
tcp        0      0 xxx.108.37.77:http          58.246.194.192:4254         SYN_RECV    
tcp        0      0 xxx.108.37.77:http          122.48.0.89:12923           SYN_RECV    
tcp        0      0 xxx.108.37.77:http          218.22.98.170:56851         SYN_RECV    
tcp        0      0 xxx.108.37.77:http          122.48.0.89:12888           SYN_RECV    
tcp        0      0 xxx.108.37.77:http          60.190.192.46:4072          SYN_RECV    
tcp        0      0 xxx.108.37.77:http          61.177.227.182:27180        SYN_RECV    
tcp        0      0 xxx.108.37.77:http          60.0.218.7:41237            SYN_RECV    
tcp        0      0 xxx.108.37.77:http          221.232.42.194:3713         SYN_RECV    
tcp        0      0 xxx.108.37.77:http          218.81.111.25:4495          SYN_RECV    
tcp        0      0 xxx.108.37.77:http          122.48.0.35:59812           SYN_RECV    
tcp        0      0 xxx.108.37.77:http          58.60.5.33:7660             SYN_RECV    
tcp        0      0 xxx.108.37.77:http          222.137.4.7:4296            SYN_RECV 


ls -l /proc/27952/fd/
rwx------  1 root root 64 Aug 22 14:44 837 -> socket:[31398309]
lrwx------  1 root root 64 Aug 22 14:44 838 -> socket:[31397749]
lrwx------  1 root root 64 Aug 22 14:44 839 -> socket:[31394222]
lrwx------  1 root root 64 Aug 22 14:38 84 -> socket:[30926430]
lrwx------  1 root root 64 Aug 22 14:44 840 -> socket:[31398135]
lrwx------  1 root root 64 Aug 22 14:44 841 -> socket:[31398930]
lrwx------  1 root root 64 Aug 22 14:44 842 -> socket:[31397984]
lrwx------  1 root root 64 Aug 22 14:44 843 -> socket:[31390139]
lrwx------  1 root root 64 Aug 22 14:44 844 -> socket:[31398331]
lrwx------  1 root root 64 Aug 22 14:44 845 -> socket:[31397572]
lrwx------  1 root root 64 Aug 22 14:44 846 -> socket:[31397546]
lrwx------  1 root root 64 Aug 22 14:44 847 -> socket:[31396094]
lrwx------  1 root root 64 Aug 22 14:44 848 -> socket:[31393666]
lrwx------  1 root root 64 Aug 22 14:44 849 -> socket:[31398932]
lrwx------  1 root root 64 Aug 22 14:38 85 -> socket:[30884712]
lrwx------  1 root root 64 Aug 22 14:44 852 -> socket:[31397555]
lrwx------  1 root root 64 Aug 22 14:44 856 -> socket:[31390278]
lrwx------  1 root root 64 Aug 22 14:44 858 -> socket:[31392652]
lrwx------  1 root root 64 Aug 22 14:44 859 -> socket:[31392710]
lrwx------  1 root root 64 Aug 22 14:38 86 -> socket:[30883810]
lrwx------  1 root root 64 Aug 22 14:38 87 -> socket:[30913192]
lrwx------  1 root root 64 Aug 22 14:38 88 -> socket:[30943036]
lrwx------  1 root root 64 Aug 22 14:38 89 -> socket:[31133080]
lrwx------  1 root root 64 Aug 22 14:38 9 -> socket:[30951877]
lrwx------  1 root root 64 Aug 22 14:38 90 -> socket:[30999630]
lrwx------  1 root root 64 Aug 22 14:38 91 -> socket:[31134432]
lrwx------  1 root root 64 Aug 22 14:38 92 -> socket:[30928870]
lrwx------  1 root root 64 Aug 22 14:38 93 -> socket:[30975324]
lrwx------  1 root root 64 Aug 22 14:38 94 -> socket:[30936083]


 wyezl 回复于:2006-08-22 14:52:50

引用:原帖由 思一克 于 2006-8-22 14:41 发表
to wyezl,

FD泄露,原因就是没有close是无疑问的。
WHY MEIYOU close?
就是事件有的时候(比如网络坏等原因)没有到来。 



这种情况怎么处理才好呢?


 思一克 回复于:2006-08-22 14:55:05

你可以设置一个timeout, 超过的cfd(在ACCPTE处)一律关闭


 wyezl 回复于:2006-08-22 14:56:56

引用:原帖由 nuclearweapon 于 2006-8-22 14:33 发表


由于有SO_KEEPALIVE可以避免这种情况吧(lz的程序也做了处理)。
否则就是client有问题,一直连着不放。 



我没有支持KEEPALIVE。发送完处理,立刻就关闭描述符了。


 wyezl 回复于:2006-08-22 15:01:52

引用:原帖由 思一克 于 2006-8-22 14:55 发表
你可以设置一个timeout, 超过的cfd(在ACCPTE处)一律关闭 


怎么为每个描述符设置超时?


 nuclearweapon 回复于:2006-08-22 15:01:58

引用:原帖由 wyezl 于 2006-8-22 14:51 发表



这是只监视1024个fds的时候的部分贴图。

# netstat -a
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address               Foreign Address             State ... 




难道有人攻击你:-(

SYN_RECV有多少个!


 nuclearweapon 回复于:2006-08-22 15:04:54

你打开tcp_syncookies
试试。
再做测试


 思一克 回复于:2006-08-22 15:07:31

可能不是好方法:

while( ......... accept()  ....) {


  ....这里检查全局的time_t fd_create[5000];

}

关闭时设置fd_create[fd] = 0;


 wyezl 回复于:2006-08-22 15:11:15

引用:原帖由 nuclearweapon 于 2006-8-22 15:01 发表



难道有人攻击你:-(

SYN_RECV有多少个! 



几百个吧。贴出来。省略一部分后面的。
# netstat -a
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address               Foreign Address             State      
tcp        0      0 *:32768                     *:*                         LISTEN      
tcp        0      0 *:sunrpc                    *:*                         LISTEN      
tcp        0      0 *:http                      *:*                         LISTEN      
tcp        0      0 xxx.108.37.77:http          58.217.195.47:4689          SYN_RECV    
tcp        0      0 xxx.108.37.77:http          58.47.42.74:2899            SYN_RECV    
tcp        0      0 xxx.108.37.77:http          218.68.242.127:1238         SYN_RECV    
tcp        0      0 xxx.108.37.77:http          222.67.10.49:30384          SYN_RECV    
tcp        0      0 xxx.108.37.77:http          pc68.broad.dynamic.xm.:2215 SYN_RECV    
tcp        0      0 xxx.108.37.77:http          220.191.231.198:47700       SYN_RECV    
tcp        0      0 xxx.108.37.77:http          218.77.186.194:63425        SYN_RECV    
tcp        0      0 xxx.108.37.77:http          220.207.230.113:3652        SYN_RECV    
tcp        0      0 xxx.108.37.77:http          60.7.59.197:3216            SYN_RECV    
tcp        0      0 xxx.108.37.77:http          123.49.160.226:3127         SYN_RECV    
warning, got duplicate tcp line.
tcp        0      0 xxx.108.37.77:http          122.48.0.89:13698           SYN_RECV    
tcp        0      0 xxx.108.37.77:http          58.67.158.106:krb524        SYN_RECV    
tcp        0      0 xxx.108.37.77:http          218.79.187.16:3129          SYN_RECV    
tcp        0      0 xxx.108.37.77:http          122.48.0.89:13680           SYN_RECV    
tcp        0      0 xxx.108.37.77:http          60.171.192.39:2531          SYN_RECV    
tcp        0      0 xxx.108.37.77:http          60.216.170.48:xxx5          SYN_RECV    
warning, got duplicate tcp line.
tcp        0      0 xxx.108.37.77:http          218.22.68.194:1101          SYN_RECV    
tcp        0      0 xxx.108.37.77:http          219.137.172.101:15053       SYN_RECV    
tcp        0      0 xxx.108.37.77:http          61.141.94.21:4748           SYN_RECV    
tcp        0      0 xxx.108.37.77:http          58.24.101.69:4188           SYN_RECV    
tcp        0      0 xxx.108.37.77:http          222.82.225.134:3118         SYN_RECV    
tcp        0      0 xxx.108.37.77:http          59.52.119.145:55806         SYN_RECV    
tcp        0      0 xxx.108.37.77:http          124.248.1.69:50344          SYN_RECV    
tcp        0      0 xxx.108.37.77:http          220.171.79.196:3014         SYN_RECV    
tcp        0      0 xxx.108.37.77:http          123.49.164.148:55258        SYN_RECV    
tcp        0      0 xxx.108.37.77:http          212.193.163.60.broad.:63429 SYN_RECV    
tcp        0      0 xxx.108.37.77:http          122.48.0.89:13754           SYN_RECV    
tcp        0      0 xxx.108.37.77:http          61.188.210.2:3532           SYN_RECV    
tcp        0      0 xxx.108.37.77:http          122.48.0.89:13752           SYN_RECV    


[root@sina src]# netstat -an | more
warning, got duplicate tcp line.
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address               Foreign Address             State      
tcp        0      0 0.0.0.0:32768               0.0.0.0:*                   LISTEN      
tcp        0      0 0.0.0.0:111                 0.0.0.0:*                   LISTEN      
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN      
tcp        0      0 xxx.108.37.77:80            xxx.103.215.242:62165       SYN_RECV    
tcp        0      0 xxx.108.37.77:80            220.191.231.198:47700       SYN_RECV    
tcp        0      0 xxx.108.37.77:80            218.246.73.21:60164         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            222.64.136.219:2881         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            123.49.160.226:3127         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            60.63.11.185:22834          SYN_RECV    
tcp        0      0 xxx.108.37.77:80            58.51.39.146:1870           SYN_RECV    
tcp        0      0 xxx.108.37.77:80            122.48.0.89:13698           SYN_RECV    
tcp        0      0 xxx.108.37.77:80            211.147.240.74:3076         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            59.54.226.64:1135           SYN_RECV    
tcp        0      0 xxx.108.37.77:80            218.28.166.198:61757        SYN_RECV    
tcp        0      0 xxx.108.37.77:80            222.82.225.134:3118         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            58.35.242.69:23660          SYN_RECV    
tcp        0      0 xxx.108.37.77:80            211.92.156.131:1210         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            221.5.82.81:2100            SYN_RECV    
tcp        0      0 xxx.108.37.77:80            220.171.79.196:3014         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            60.163.193.212:63429        SYN_RECV    
tcp        0      0 xxx.108.37.77:80            122.48.0.89:13754           SYN_RECV    
tcp        0      0 xxx.108.37.77:80            61.188.210.2:3532           SYN_RECV    
tcp        0      0 xxx.108.37.77:80            218.82.23.151:64811         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            122.48.0.89:13752           SYN_RECV    
tcp        0      0 xxx.108.37.77:80            218.18.33.108:4641          SYN_RECV    
tcp        0      0 xxx.108.37.77:80            211.95.165.175:61439        SYN_RECV    
tcp        0      0 xxx.108.37.77:80            218.28.188.86:52324         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            211.92.156.131:1215         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            211.92.156.131:1206         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            218.71.200.192:1503         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            221.200.137.120:1619        SYN_RECV    
tcp        0      0 xxx.108.37.77:80            218.59.106.182:53008        SYN_RECV    
tcp        0      0 xxx.108.37.77:80            211.69.18.125:3158          SYN_RECV    
tcp        0      0 xxx.108.37.77:80            218.81.193.198:1434         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            61.144.254.129:50050        SYN_RECV    
tcp        0      0 xxx.108.37.77:80            211.92.156.131:1216         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            218.28.58.69:9898           SYN_RECV    
tcp        0      0 xxx.108.37.77:80            220.234.241.178:1679        SYN_RECV    
tcp        0      0 xxx.108.37.77:80            219.242.196.109:2261        SYN_RECV    
tcp        0      0 xxx.108.37.77:80            124.21.243.228:1648         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            221.200.137.120:1620        SYN_RECV    
tcp        0      0 xxx.108.37.77:80            222.35.126.211:1336         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            221.234.146.160:2188        SYN_RECV    
tcp        0      0 xxx.108.37.77:80            222.169.187.100:3529        SYN_RECV    
tcp        0      0 xxx.108.37.77:80            122.48.0.89:13748           SYN_RECV    
--More--warning, got duplicate tcp line.
warning, got duplicate tcp line.
warning, got duplicate tcp line.
tcp        0      0 xxx.108.37.77:80            218.246.73.21:60165         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            221.196.131.130:4444        SYN_RECV    
tcp        0      0 xxx.108.37.77:80            220.174.8.13:12043          SYN_RECV    
tcp        0      0 xxx.108.37.77:80            211.95.165.175:61440        SYN_RECV    
tcp        0      0 xxx.108.37.77:80            220.205.30.17:1519          SYN_RECV    
tcp        0      0 xxx.108.37.77:80            61.188.210.2:3531           SYN_RECV    
tcp        0      0 xxx.108.37.77:80            60.163.193.212:63427        SYN_RECV    
tcp        0      0 xxx.108.37.77:80            218.94.127.135:30598        SYN_RECV    
tcp        0      0 xxx.108.37.77:80            219.155.143.97:1120         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            221.7.131.131:4331          SYN_RECV    
tcp        0      0 xxx.108.37.77:80            211.147.240.74:3077         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            210.76.66.35:1524           SYN_RECV    
tcp        0      0 xxx.108.37.77:80            61.138.254.47:29233         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            59.35.87.21:11079           SYN_RECV    
tcp        0      0 xxx.108.37.77:80            219.242.196.109:2260        SYN_RECV    
tcp        0      0 xxx.108.37.77:80            220.205.30.17:1518          SYN_RECV    
tcp        0      0 xxx.108.37.77:80            58.62.84.52:4315            SYN_RECV    
tcp        0      0 xxx.108.37.77:80            221.216.74.228:4444         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            222.169.187.100:3528        SYN_RECV    
tcp        0      0 xxx.108.37.77:80            211.92.156.131:1207         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            222.209.217.21:38807        SYN_RECV    
tcp        0      0 xxx.108.37.77:80            219.238.191.17:17679        SYN_RECV    
tcp        0      0 xxx.108.37.77:80            61.172.137.186:4075         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            211.92.156.131:1212         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            221.214.13.109:17600        SYN_RECV    
tcp        0      0 xxx.108.37.77:80            218.23.149.98:46060         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            221.222.116.178:1658        SYN_RECV    
tcp        0      0 xxx.108.37.77:80            xxx.103.215.242:62164       SYN_RECV    
tcp        0      0 xxx.108.37.77:80            222.173.191.91:1143         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            61.242.112.118:59158        SYN_RECV    
tcp        0      0 xxx.108.37.77:80            222.209.217.21:38551        SYN_RECV    
tcp        0      0 xxx.108.37.77:80            219.129.164.182:62607       SYN_RECV    
tcp        0      0 xxx.108.37.77:80            58.60.67.4:48095            SYN_RECV    
tcp        0      0 xxx.108.37.77:80            211.92.156.131:1213         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            122.48.0.89:13694           SYN_RECV    
tcp        0      0 xxx.108.37.77:80            218.87.71.62:2363           SYN_RECV    
tcp        0      0 xxx.108.37.77:80            61.173.14.106:4444          SYN_RECV    
tcp        0      0 xxx.108.37.77:80            220.234.241.178:1678        SYN_RECV    
tcp        0      0 xxx.108.37.77:80            210.21.209.145:5554         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            122.48.0.89:13750           SYN_RECV    
tcp        0      0 xxx.108.37.77:80            59.35.87.21:11080           SYN_RECV    
tcp        0      0 xxx.108.37.77:80            61.172.137.186:4076         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            222.67.94.46:1434           SYN_RECV    
tcp        0      0 xxx.108.37.77:80            122.48.0.89:13697           SYN_RECV    
tcp        0      0 xxx.108.37.77:80            61.242.112.118:59160        SYN_RECV    
tcp        0      0 xxx.108.37.77:80            58.35.242.69:23659          SYN_RECV    
--More--warning, got duplicate tcp line.
warning, got duplicate tcp line.
tcp        0      0 xxx.108.37.77:80            61.181.71.50:3946           SYN_RECV    
tcp        0      0 xxx.108.37.77:80            211.92.156.131:1209         SYN_RECV    
tcp        0      0 xxx.108.37.77:80            60.63.11.185:22833          SYN_RECV    
tcp        0      0 xxx.108.37.77:80            122.48.0.89:13744           SYN_RECV    
tcp        0      0 xxx.108.37.77:80            222.137.152.197:4755        SYN_RECV    
tcp        0      0 xxx.108.37.77:80            220.169.5.239:3676          SYN_RECV    
tcp        0      0 127.0.0.1:631               0.0.0.0:*                   LISTEN      
tcp        0      0 127.0.0.1:25                0.0.0.0:*                   LISTEN      
tcp        0      0 xxx.108.37.77:80            221.6.163.131:35293         TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            221.198.127.25:1956         TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            60.2.106.52:58968           TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            221.222.144.24:1618         TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            211.158.132.14:1808         TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            218.89.188.200:60118        TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            221.0.180.142:58305         TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            61.51.223.223:1992          TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            61.170.213.11:14704         TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            219.136.26.220:3765         TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            211.158.81.195:4087         TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            218.71.200.192:1460         TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            221.5.152.50:37803          TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            210.21.232.236:33515        TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            221.198.127.25:1957         TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            221.15.17.77:1878           TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            221.1.244.62:1230           TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            61.155.209.139:2875         TIME_WAIT   
tcp        1      1 xxx.108.37.77:80            60.186.14.190:13808         CLOSING     
tcp        0      0 xxx.108.37.77:80            60.208.111.253:57016        TIME_WAIT   
tcp        1      1 xxx.108.37.77:80            219.145.113.15:52970        CLOSING     
tcp        0      0 xxx.108.37.77:80            61.170.213.11:14705         TIME_WAIT   
tcp        1      1 xxx.108.37.77:80            xxx.106.180.254:2266        CLOSING     
tcp        1      1 xxx.108.37.77:80            222.68.248.150:7632         CLOSING     
tcp        0      0 xxx.108.37.77:80            60.17.17.149:62063          TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            60.0.16.66:3159             TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            58.101.33.97:3616           TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            125.32.0.114:1367           TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            125.33.217.83:3502          TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            71.135.63.37:61595          TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            218.26.227.9:31478          TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            220.161.163.113:1141        TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            221.1.244.62:1229           TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            60.2.106.52:58970           TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            221.15.17.77:1877           TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            222.64.14.150:64545         TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            222.67.166.24:2299          TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            61.51.223.223:1994          TIME_WAIT   
--More--warning, got duplicate tcp line.
warning, got duplicate tcp line.
tcp        0      0 xxx.108.37.77:80            61.155.18.18:56733          TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            60.15.21.5:12313            TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            58.33.225.117:2739          TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            61.167.60.224:58498         TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            58.60.5.33:7454             TIME_WAIT   
tcp        0    243 xxx.108.37.77:80            218.71.200.192:1718         FIN_WAIT1   
tcp        0      0 xxx.108.37.77:80            123.49.164.148:55288        TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            125.33.217.83:3501          TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            221.214.13.109:47024        TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            221.218.117.87:17919        TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            218.108.44.10:21325         TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            124.200.18.190:3484         TIME_WAIT   
tcp        0    300 xxx.108.37.77:80            221.218.117.87:26879        FIN_WAIT1   
tcp        0    567 xxx.108.37.77:80            221.218.117.87:27135        FIN_WAIT1   
tcp        0      0 xxx.108.37.77:80            218.26.227.9:31479          TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            220.161.163.113:1140        TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            221.222.144.24:1617         TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            60.2.106.52:58971           TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            221.5.181.31:3752           TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            61.49.166.124:62700         TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            221.0.180.142:58306         TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            61.51.223.223:1995          TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            60.208.111.253:57018        TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            xxx.111.152.6:56054         TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            58.33.225.117:2738          TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            61.181.245.85:25618         TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            123.49.164.148:55289        TIME_WAIT   
tcp        1      1 xxx.108.37.77:80            125.92.214.174:6619         CLOSING     
tcp        0      0 xxx.108.37.77:80            124.200.18.190:3483         TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            60.166.100.106:48296        TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            222.223.6.176:40086         ESTABLISHED 
tcp        0      0 xxx.108.37.77:80            124.42.126.70:55826         TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            221.226.242.212:64827       TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            221.198.127.25:1952         TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            222.64.14.150:64295         TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            xxx.106.113.61:6182         TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            221.229.12.88:4273          TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            61.49.166.124:62699         TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            221.8.9.91:5210             TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            210.21.196.86:11655         TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            218.87.255.183:3552         TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            61.181.250.190:32782        TIME_WAIT   
tcp        0      0 xxx.108.37.77:80            125.33.217.83:3499          TIME_WAIT


 wyezl 回复于:2006-08-22 15:12:21

引用:原帖由 nuclearweapon 于 2006-8-22 15:04 发表
你打开tcp_syncookies
试试。
再做测试 


怎么打开?


 思一克 回复于:2006-08-22 15:14:30

wyezl,

攻击不会影响FD。FD是已经建立的连接没close.


 思一克 回复于:2006-08-22 15:15:40

这个帖子可以做为精华了。因为问题微妙又棘手,有普遍性,尤其对与EPOLL


 nuclearweapon 回复于:2006-08-22 15:17:25

如果一直有大量的SYN_RECV就有可能是攻击。

echo 1 > /proc/sys/net/ipv4/tcp_syncookies
可以打开。

下边还有几个都是对付 ddos的。太具体要自己查查。


 wyezl 回复于:2006-08-22 15:23:30

引用:原帖由 思一克 于 2006-8-22 15:14 发表
wyezl,

攻击不会影响FD。FD是已经建立的连接没close. 




我暂时的方法是描述符用完了,就退出。
由监视程序定时检查和重启。
这不知道是不是epoll自身的缺陷。


 nuclearweapon 回复于:2006-08-22 15:25:25

引用:原帖由 思一克 于 2006-8-22 15:14 发表
wyezl,

攻击不会影响FD。FD是已经建立的连接没close. 



我记得和斑竹有一些出入。
因为:
只要有socket就会有一个inode,也就会有一个fd。而不是连接以后才会有fd的。
对于linux2。6来说
每当在内核创建完struct socket后,就会调用sock_map_fd()在调用进程创建一个fd。

如果有SYN_RECV状态,也就有了struct socket,也就有了inode,进而有了fd。
希望指正!

[ 本帖最后由 nuclearweapon 于 2006-8-22 15:27 编辑 ]


 思一克 回复于:2006-08-22 15:26:40

应该不是epoll本身的问题。epoll采样事件,如果事件没有来它也无能为力。timeout是必须的


 wyezl 回复于:2006-08-22 15:27:28

引用:原帖由 思一克 于 2006-8-22 15:15 发表
这个帖子可以做为精华了。因为问题微妙又棘手,有普遍性,尤其对与EPOLL 



如果能讨论出一个成熟的,通用的epoll模型。 加精华也不亏。呵呵。
我继续线上测试。

uname -a
Linux xxx.com.cn 2.6.9-34.EL #1 Wed Mar 8 00:07:35 CST 2006 i686 i686 i386 GNU/Linux
[finance@sina src]$ cat /etc/issue
CentOS release 4.1 (Final)
Kernel \r on an \m


 思一克 回复于:2006-08-22 15:30:35

TO nuclearweapon,

你说的对。但他的问题是accept之后的fd被耗尽了,那就是有连接的socket.

如果那些DDOS攻击,往往是半连接(部分IP包),accept不了。


引用:原帖由 nuclearweapon 于 2006-8-22 15:25 发表


我记得和斑竹有一些出入。
因为:
只要有socket就会有一个inode,也就会有一个fd。而不是连接以后才会有fd的。
对于linux2。6来说
每当在内核创建完struct socket后,就会调用sock_map_fd()在调用进程创建 ... 




 nuclearweapon 回复于:2006-08-22 15:35:28

引用:原帖由 思一克 于 2006-8-22 15:30 发表
TO nuclearweapon,

你说的对。但他的问题是accept之后的fd被耗尽了,那就是有连接的socket.

如果那些DDOS攻击,往往是半连接(部分IP包),accept不了。


 




就是这半连接的socket把fd用完了。
因为只有有了socket才可能有sycrcv状态。


 思一克 回复于:2006-08-22 15:42:47

To nuclearweapon,

也有可能是攻击引起的。让他继续实验。
半连接accept能成功返回fd吗?我不是十分肯定。


 nuclearweapon 回复于:2006-08-22 15:45:33

对于半连接来说accpet是不能返回了,但是在内核中fd已经建立起来了,也就消耗了一个进程的可用fd数量。


 wyezl 回复于:2006-08-22 15:50:57

引用:原帖由 思一克 于 2006-8-22 15:42 发表
To nuclearweapon,

也有可能是攻击引起的。让他继续实验。
半连接accept能成功返回fd吗?我不是十分肯定。 



现在访问量下降了。
SYN_RECV 也下降到了只有20~30个。

恶意攻击的可能性比较小。
是不是由于我的次序造成的?


 思一克 回复于:2006-08-22 15:52:56

TO nuclearweapon,

你肯定没有建立的连接,没有accept的也消耗KERNEL中的fd吗? 我不SURE


 wyezl 回复于:2006-08-22 15:54:38

引用:原帖由 nuclearweapon 于 2006-8-22 15:45 发表
对于半连接来说accpet是不能返回了,但是在内核中fd已经建立起来了,也就消耗了一个进程的可用fd数量。 




我可以统计一段时间内, accpet的总数,和close的总数。看他们的差是不是等于。
/etc/pid/fd 下面的fd数。


 思一克 回复于:2006-08-22 16:00:55

TO nuclearweapon,

我刚才看了KERNEL代码,看到fd消耗只有3个函数socket() , accept(), socketpair(), 而且都是成功后才消耗fd. 网络程序其它任何地方没有看到用fd的?

半连接能消耗fd吗,我不是很清楚。如果你清楚就写出来。

谢谢

引用:原帖由 nuclearweapon 于 2006-8-22 15:45 发表
对于半连接来说accpet是不能返回了,但是在内核中fd已经建立起来了,也就消耗了一个进程的可用fd数量。 




 wyezl 回复于:2006-08-22 16:05:40

现在访问量比较少的时候。fd随时间变化情况。当然是重新启动之后测试的。这样看起来基本没问题。
压力上来后就漫漫变了。

[root@xxx ~]# ls /proc/28305/fd/
0   10  12  14  16  18  2   21  23  25  28  4   6   8   
1   11  13  15  17  19  20  22  24  27  3   5   7   9   
[root@xxx ~]# ls /proc/28305/fd/
0   10  12  14  16  18  2   21  23  25  28  4   6   8   
1   11  13  15  17  19  20  22  24  27  3   5   7   9   
[root@xxx ~]# ls /proc/28305/fd/
0   1   10  11  12  13  14  15  16  17  18  19  2   20  21  22  24  3   4   5   6   7   8   9   
[root@xxx ~]# ls /proc/28305/fd/
0   1   11  12  13  14  15  16  17  18  2   20  21  24  3   4   5   6   8   9   
[root@xxx ~]# ls /proc/28305/fd/
0   1   10  11  12  13  14  15  16  17  18  2   20  21  24  3   4   5   6   8   9   
[root@xxx ~]# ls /proc/28305/fd/
0   1   10  11  12  13  14  15  16  17  18  2   20  21  24  3   4   5   6   
[root@xxx ~]# ls /proc/28305/fd/
0   1   10  11  12  13  14  15  16  17  18  2   24  3   4   5   6   7   8   9   
[root@xxx ~]# ls /proc/28305/fd/
0   1   10  11  12  13  14  15  18  2   3   4   5   6   7   8   9   
[root@xxx ~]# ls /proc/28305/fd/
0   1   10  11  12  13  14  15  16  18  2   3   4   5   6   7   8   
[root@xxx ~]# ls /proc/28305/fd/
0   1   10  11  13  14  15  16  17  18  2   3   4   5   6   7   8   9   
[root@xxx ~]# ls /proc/28305/fd/
0   1   10  11  12  13  14  15  16  17  18  19  2   3   4   5   6   7   8   9   
[root@xxx ~]# ls /proc/28305/fd/
0   1   10  11  12  13  14  15  16  17  2   3   4   5   6   7   8   9   
[root@xxx ~]# ls /proc/28305/fd/
0   1   11  12  13  14  15  17  19  2   3   4   5   6   7   8   9   
[root@xxx ~]# ls /proc/28305/fd/
0   1   10  11&