免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 8857 | 回复: 3
打印 上一主题 下一主题

[C++] socket-server通过fork()子进程创建多连接ESTABLISHED状态无法释放问题求解 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-06-29 19:08 |只看该作者 |倒序浏览
本帖最后由 cicy821@126.com 于 2011-06-29 19:21 编辑

写一个socket-server程序,此程序需要支持多连接,采用的是每接收到一个client的connection后fork出来一个子进程进行处理。
源码如下:
          sigset(SIGPIPE, SIG_IGN);          //忽略SIGPIPE信号,忽略SIGCHLD信号,父进程不关心子进程何时退出,有系统回收资源。
                sigset(SIGCHLD, SIG_IGN);
                int pids=waitpid(-1, 0, WNOHANG); /*wait any child process to exit */      //是否多余?
                int iSock=TcpServerSocket(listenport);
                if(iSock<0)
                {
                                close(iSock);
                                iSock=-1;
                                sleep(1);
                }
                                               
                len = sizeof(sockaddr);
                asock = accept(iSock, (struct sockaddr *)&sin, &len);
                if(asock < 0)
                {
                        continue;
                }
               
                if( (cpid=fork())==0 )        /* child process */
                {
                        // 需要关闭listen状态的句柄
                        //close(iSock);                //子进程是否需要关闭父进程的listen句柄?个人觉得应该不应该关闭                  
AGTCLIENT agtclnt;
                        agtclnt.start(asock);                      //子进程执行函数,函数为死循环除非异常否则永远不会退出

                        exit(0);
                }
                else if(cpid > 0) /*parent process*/
                {
                        /*close(asock);
                        asock = -1;*/                            //父进程是否需要关闭子进程的accept句柄?个人觉得应该不应该关闭  

                        sleep(10);

                        //if((cpid=waitpid(cpid,&status,WNOHANG))<0)  /*wait for child process exit*/       //此处还需要父进程waitpid吗?前面已经做了信号忽略。主要问题是子进程为死循环独立运行,永远不会返回或者退出,除非出现异常,所以父进程永远等不到子进程的退出。                        //olog.logwrite(LOG_TIME|MAJOR,mainlogname,"waitpid error\n");
                }
            }


请大虾指导一下,我是否还有其他地方没有注意,或者请大虾分享一下写的支持socket多连接的实现方案。
我重点关注了:
1、增加信号忽略避免僵尸进程


目前这个状态的程序在使用client测试时,如果出现异常就出现连接状态不释放的情况。
即此程序监听的端口查看状态为,多个 ESTABLISHED状态,而实际的连接确只有二个:
netstat -an |grep 9090
tcp        0      0  127.0.0.1.60731        127.0.0.1.9090          ESTABLISHED
tcp        0      0  16.157.88.223.9090     16.157.88.223.60924     ESTABLISHED
tcp        0      0  16.157.88.223.9090     16.157.88.223.65240     ESTABLISHED
tcp        0      0  127.0.0.1.52236        127.0.0.1.9090          ESTABLISHED
tcp        0      0  16.157.88.223.9090     16.157.88.223.65500     ESTABLISHED
tcp        0      0  16.157.88.223.65500    16.157.88.223.9090      ESTABLISHED
tcp        0      0  127.0.0.1.9090         127.0.0.1.54030         ESTABLISHED
tcp        0      0  127.0.0.1.54030        127.0.0.1.9090          ESTABLISHED
tcp        0      0  16.157.88.223.65240    16.157.88.223.9090      ESTABLISHED
tcp        0      0  127.0.0.1.9090         127.0.0.1.60731         ESTABLISHED
tcp        0      0  16.157.88.223.60924    16.157.88.223.9090      ESTABLISHED
tcp        0      0  16.157.88.223.61817    16.157.88.223.9090      ESTABLISHED
tcp        0      0  127.0.0.1.9090         127.0.0.1.52236         ESTABLISHED
tcp        0      0  127.0.0.1.63711        127.0.0.1.9090          ESTABLISHED
tcp        0      0  16.157.88.223.9090     16.157.88.223.61150     ESTABLISHED
tcp        0      0  16.157.88.223.61150    16.157.88.223.9090      ESTABLISHED
tcp        0      0  16.157.88.223.9090     16.157.88.223.61817     ESTABLISHED
tcp        0      0  16.157.88.223.56796    16.157.88.223.9090      ESTABLISHED
tcp        0      0  127.0.0.1.9090         127.0.0.1.63711         ESTABLISHED
tcp        0      0  *.9090                 *.*                     LISTEN
tcp        0      0  16.157.88.223.9090     16.157.88.223.56796     ESTABLISHED


如上的9090端口可以监听是程序设置了端口复用。实际的连接只有二个,其他连接都是非正常连接。超过了keepalive_interval=15秒系统的 ESTABLISHED
状态也是不释放。
使用lsof工具看9090端口连接,没有看到任何应用程序连接此端口,此端口无任何记录。

为什么ESTABLISHED状态不释放?查看了系统设计的keepalive_interval为15000毫秒=15秒。


请大虾支招,深表感谢。

论坛徽章:
0
2 [报告]
发表于 2011-06-30 09:12 |只看该作者
应该先fork子进程,再把任务分配到每个子进程上

论坛徽章:
0
3 [报告]
发表于 2011-06-30 10:15 |只看该作者
回复 2# int-main


                   if( (cpid=fork())==0 )        /* child process */
                {
                        // 需要关闭listen状态的句柄
                        //close(iSock);                //子进程是否需要关闭父进程的listen句柄?个人觉得应该不应该关闭                  
               AGTCLIENT agtclnt;
                        agtclnt.start(asock);                      //子进程执行函数,函数为死循环除非异常否则永远不会退出

                        exit(0);
                }


就是先fork子进程,然后让子进程独立运行执行 agtclnt.start(asock); 函数中任务。

论坛徽章:
0
4 [报告]
发表于 2011-07-04 18:37 |只看该作者
问题解决,自己结贴。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP