Chinaunix

标题: ★请教:fork进程遇到端口状态不释放的问题★ [打印本页]

作者: testtt    时间: 2003-07-08 15:45
标题: ★请教:fork进程遇到端口状态不释放的问题★
气死我了!!!!刚写完了帖子!!!!!脚碰到了电源!!!!!!

重写!!!!!!!!!疯了我!!!!

废话少说,请教大家:

写了一个C/S程序,简单介绍一下:Server在6666端口监听(使用netstat可以看到6666端口状态为LISTEN),准备接收来自Client的命令,当收到Client的“启动”命令时,Server fork()一个进程,execlp()另一个程序AAA,该AAA程序内为循环,一直运行,此时使用netstat可以看到6666端口增加一个状态为CLOSE_WAIT,此时Client依然可以向Server发送其他命令。只有当Client发送“停止AAA”的命令或者手动结束AAA进程时,该CLOSE_WAIT状态才消失。

之所以为这个问题苦恼,是因为:如果AAA在运行过程中,server被错误终止,则该CLOSE_WAIT将一直存在下去,尽管Server的进程已经不存在。此时再结束AAA,也无济于事。重启Server后,因为CLOSE_WAIT状态一直存在,Server将无法接收来自Client的命令,且Client连接Server:6666一次,Server便增加一个CLOSE_WAIT状态。我在多个UNIX平台(sun/hp/aix等)上都试过,这种CLOSE_WAIT状态不会自己关闭。所以每次都很痛苦,需要重启网卡。要么就重启系统。

请各位不吝赐教:
1、为什么fork一个进程便会产生一个CLOSE_WAIT状态?
2、并且这种状态必须随着子进程的终止才能结束?
3、有没有方法避免或者解决这种CLOSE_WAIT的方法?

我曾经尝试向6666端口发送RST标志位=1或者FIN=1的TCP包,也不能reset这个连接。
作者: mushuang    时间: 2003-07-08 16:03
标题: ★请教:fork进程遇到端口状态不释放的问题★
服务器有没有close掉那个端口

fork后服务器的端口socketid还存在 客户的端口socketid也存在
这时这个socketid 引用数=2  
所以服务端应该close
作者: andyY    时间: 2003-07-08 16:38
标题: ★请教:fork进程遇到端口状态不释放的问题★
好象有个可重用的选项的,可惜记不到了
作者: 无双    时间: 2003-07-08 17:43
标题: ★请教:fork进程遇到端口状态不释放的问题★
看精华中的SETSOCKOPT

选项是REUSEADDR或是REUSEOPORT
作者: gadfly    时间: 2003-07-08 17:46
标题: ★请教:fork进程遇到端口状态不释放的问题★
在socket之后
setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, ...)
设置可重用这个端口


另外你exec方式执行AAA,AAA复制了父进程的描述符表,最好将所有不用的描述符关闭,像做daemon的方式那样,将所有的描述符关闭一遍。
作者: testtt    时间: 2003-07-08 19:07
标题: ★请教:fork进程遇到端口状态不释放的问题★
多谢楼上各位!!!

mushuang,我不太理解您说的

还有楼上几位兄台,我看了精华区的文章,如果重用端口,那之前出现的CLOSE_WAIT不是依然存在吗?并且我想知道这个CLOSE_WAIT产生的原因。请教各位了。

gadfly,描述符我已关闭了。
作者: 无双    时间: 2003-07-08 19:09
标题: ★请教:fork进程遇到端口状态不释放的问题★
键盘的TCP讨论(精华中)
里面有对CLOSE——WAIT说明
你想知道的话看看
或是UNIX网络编程中对CLOSE——WAIT状态的说明
作者: jobman    时间: 2003-07-09 03:18
标题: ★请教:fork进程遇到端口状态不释放的问题★
mushuang 说的对, 必须在 accept之后, 父进程关闭返回的
socket, 重用不解决根本问题.
作者: jobman    时间: 2003-07-09 03:44
标题: ★请教:fork进程遇到端口状态不释放的问题★
忘了一句, 同时在子进程中关闭父进程的socket, 太绕口了,看

mainsock = socket(..);
.....
subsock=accept( mainsock....)

i=fock( .....)
if( i >; 0 )
{
close subsock;
}
else if( i == 0 )
{
close mainsock;
}
else
{
error;
}r
作者: testtt    时间: 2003-07-09 11:04
标题: ★请教:fork进程遇到端口状态不释放的问题★
jobman,我可是万万没有忘记closeaccept()的
究竟是怎么了?我再看看  多谢各位
作者: jobman    时间: 2003-07-09 13:36
标题: ★请教:fork进程遇到端口状态不释放的问题★
最干脆的,把 SO_LINGER 设置上, 连 TIME_WAIT 都没有了.
作者: 蓝色键盘    时间: 2003-07-10 13:36
标题: ★请教:fork进程遇到端口状态不释放的问题★
了一个C/S程序,简单介绍一下:Server在6666端口监听(使用netstat可以看到6666端口状态为LISTEN),准备接收来自Client的命令,当收到Client的“启动”命令时,Server fork()一个进程,execlp()另一个程序AAA,该AAA程序内为循环,一直运行,此时使用netstat可以看到6666端口增加一个状态为CLOSE_WAIT,此时Client依然可以向Server发送其他命令。只有当Client发送“停止AAA”的命令或者手动结束AAA进程时,该CLOSE_WAIT状态才消失。

【遇到类似的问题的时候,解决的办法很简单,你用netstat -a|grep 6666看看,出现close_wait状态的是拿一个端点,这样就知道是那个进程执行了close操作或者进程异常】

之所以为这个问题苦恼,是因为:如果AAA在运行过程中,server被错误终止,则该CLOSE_WAIT将一直存在下去,尽管Server的进程已经不存在。

【很明显,你的描述是因为server执行了close引起的,因为aaa仍然在运行,因此出现在aaa这端的tcp状态一直在维持着】

此时再结束AAA,也无济于事。重启Server后,因为CLOSE_WAIT状态一直存在,Server将无法接收来自Client的命令,且Client连接Server:6666一次,Server便增加一个CLOSE_WAIT状态。我在多个UNIX平台(sun/hp/aix等)上都试过,这种CLOSE_WAIT状态不会自己关闭。所以每次都很痛苦,需要重启网卡。要么就重启系统。

【这个问题的引起可以通过kill服务和客户来快速解决,你如上的描述是不确切的,“此时再结束AAA,也无济于事”,你在结束后便迫不及待的用netstat -a|grep 6666看了状态,此时一般正在处于四分节终止的某一过程中,因为这个过程需要一段时间,因此你认为无济于事。】

请各位不吝赐教:
1、为什么fork一个进程便会产生一个CLOSE_WAIT状态?

【不是fork就会成生close_wait,而是应用程序的问题,具体参看论坛重的例子代码】

2、并且这种状态必须随着子进程的终止才能结束?
【哼,你不是说“此时再结束AAA,也无济于事”,现在却说种状态必须随着子进程的终止才能结束】

3、有没有方法避免或者解决这种CLOSE_WAIT的方法?
【有办法,问题出在应用代码】

我曾经尝试向6666端口发送RST标志位=1或者FIN=1的TCP包,也不能reset这个连接。
【很简单,因为两个断点的一段仍然存在】




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2