Chinaunix首页 | 论坛 | 博客
  • 博客访问: 538078
  • 博文数量: 142
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1452
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-12 16:28
文章分类

全部博文(142)

文章存档

2016年(10)

2015年(60)

2014年(72)

我的朋友

分类: C/C++

2014-09-17 16:17:45

并发服务器程序的轮廓

点击(此处)折叠或打开

  1. pid_t pid;
  2. int listenfd,connfd;

  3. listenfd = socket(AF_INET,SOCK_STREAM,0);

  4. bind(listenfd,...);

  5. listen(listenfd, LISTENQ);

  6. for(;;)
  7. {
  8.     connfd=accept(listenfd,...);
  9.     pid=fork();
  10.     
  11.     if(pid==0) {
  12.         close(listenfd);
  13.         doit(connfd);
  14.         close(connfd);
  15.         exit(0);
  16.     }
  17.     close(connfd);
  18. }
每一个socket描述符都有对应的引用计数,该计数存在文件表中。上面程序中打开了listenfd和connfd,引用计数分别为1和1,在fork()以后,子进程复制了父进程的socket描述符,所以listenfd和connfd的引用计数都变成了2。此时在子进程中关闭listenfd(close(listenfd)),在父进程中关闭close(connfd).这个就保证了子进程处理与客户的连接,父进程负责在监听套接字listenfd再次调用accept来接收客户的下一个连接。

如下图所示:




可能看到这,大家有疑问了? 为啥父进程调用close后没有发送FIN报文来结束连接,而子进程仍然可以用connfd进行数据处理呢?
其实,从上面分析和图示可以看出socket描述符是有引用计数的,只有当引用计数为0的时候,close才会发送FIN报文,这就解释了子进程仍然可以用connfd进行数据处理了,子进程处理完后再次调用close,此时引用计数从1变为0,最后发送FIN报文结束connfd连接。
而对于listenfd,只有在子进程中进行了close,父进程中一直保留着引用计数为1,所以父进程通过for循环可以持续accept新连接。
阅读(1153) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~