ClientSocket的错误处理(100分)

  • 主题发起人 主题发起人 ncutzcb
  • 开始时间 开始时间
N

ncutzcb

Unregistered / Unconfirmed
GUEST, unregistred user!
我的头儿设计了一个系统:
要求一个客户端连接5个服务端(服务端不一定同时在线)。
处理方法是:
在DataModule中放5个ClientSocket,将这5个控件放在一个数组中;
在一个Timer中检测各个ClientSocket的状态,
for index :=0 to Count-1 do
begin
if ClientSocketArray.Active then Continue;
ClientSocketArray.Close;
ClientSocketArray.Ip:=GetIp(i);{得到对应的IP}
ClientSocketArray.Port:= GetPort(i);{得到对应的Port}
ClientSocketArray.Open;
end;
在ClientSocket的OnError中
Socket.Close;
ErrorCode:=0;
在程序运行了大约一个小时后,出现错误:
ESocketError with message
'Windows socket error: 当该操作在进行中,由于保持活动的操作检测到一个故障,
该连接中断。 (10055), on API 'connect''. Process stopped.
请哪位大侠指点指点。
 
没有人回答?100分还少?还是问题太幼稚?
 
在定时器中快速连续不断的Open和Close,对于异步Socket是不能这样操作的。
当程序出错时,你在DOS窗口中运行netstat -na 会发现很多状态是TIME_WAIT的,
这些过一段时间就会释放,就是它造成WinSocket池用完,过一段时间就会释放了。

只要把定时器执行那段代码的时间间隔设置为稍大于60秒即可,而且对功能上没有任何损害
 
用邮件槽,容易做的多!!!
还有你在关闭以后,让系统延迟40秒再打开这个端口...
时间可以自己调
while (Now-tim<0.00001) do
Application.ProcessMessages;
 
有没有可以清除winsocket池的方法?
 
没有,主要是你关闭Client端的时候,要稍后再打开,原因就是TIME_WAIT状态占用了
系统资源。你可以用我的办法,中间延长30秒再打开。
不过我对你的程序的意思没有明白,为什么要一开一关?
 
to 张无忌:
我的客户端要连接远端的服务器(在距离很远的局域网内)。
而且要每天24小时工作。这样做是为了解决有的服务端关闭,而客户端不能关闭的情况。
要保证当服务器端启动后,客户端能够马上(时间不能太长)连接地上。
其实按照我的想法,现在系统的客户和服务端是应该调换的。但这是我们头儿设计的,没有办法。
搞得我现在非常难受。
说实在的,我对socket知之甚少。能否说得再详细一点?
现说声谢谢!
 
to 张无忌:
原来我以为close方法可以释放掉占用的系统资源,所以先Close,再Open。
现在看来是不行的。
阁下的意思是不是在ClientSocket产生连接错误的时候,
只要延时30秒,然后再Open,就可以了。
不过不明白为什么要延时30秒?是不是释放系统的时间是30秒?
要连续365×7×24小时地工作,不会发生系统资源耗尽的问题吧?比如10055错误。
 
如题目所述:
"在一个Timer中检测各个ClientSocket的状态..."
说实在的,你只要保证在这段检测代码大约60秒左右执行一次的话,在重连方面就没有问题了。
理由如下?
一个Socket的状态要经过SYN_SEND,ESTABLISHED,TIME_WAIT等等...还有一些忘了,每个状态停留的时间
由操作系统确定(据说可以通过API修改),Socket状态跟双方的连接状态也有关系,比如双方同时关闭,
则可能很快释放了,如果关闭时,对方有问题,可能在TIME_WAIT的停留时间会长些。
TClientSocket的Close方法只是向操作系统发一个消息要求关闭那个Socket的窗体句柄而已,
WINDOWS有没有真正地关闭,是没有直接控制的。
所有操作系统的最大Socket数都是有限制的,WinNT大约4000左右吧,可考虑有关的资料。
所以按你的方法,在最后出问题时,所有的可用Socket的状态都是TIME_WAIT了。
因此,解决办法是,把Open和Close的频率降低,改为大约60秒----为什么?因为WinSocket的超时时间差不多是这样。
 
还有,如果有服务器关闭了,客户端会自己关闭的,因为这个连接不存在了.......
没有必要手头关闭他...
 
我觉得一定有什么方法可以释放的。
比如flashget中连接远端的ftp服务器,就可以设定重复连接的频率,默认是5秒,
但是可以更改,并且可以设定重试的次数为无限。
因为如果间隔的时间太长,可能有数据丢失的可能。
 
to ncutzcb,
借宝地一用,谢谢了。
to everyone
按楼上各兄弟所说,出现TIME_WAIT是因为clientsocket关闭了活动sokcet,而serversocket还没有来
得及处理的而造成的。如果serversocket主动关闭活动socket,那么是不会出TIME_WAIT这个标志的。
不知道我这样理解对不对。指各位指点。
 
to ncutzcb,
如果我的理解是对的,那么你在关闭clientsocket之前,可以发一个命令到serversocket,让它执行这个
关闭命令,我想就不会出你的这个问题了吧。
 
to枫:你的解决完全不对。
按ncutzcb的思路,当他关闭自己的ClientSocket时,根本都未连接上,何来什么发消息通知呢?

另外 to ncuzcb
在flashget中,重新连接的最小间隔是5秒,但它的连接超时时间最少也是60秒,和上面我们讨论的是一样的。
如果它的连接时超时时间太短,也会面临你的问题了----10055错误:没有可用的缓冲区。
 
那么为了及时地与服务端连接上,是不是可以这样处理:
在程序开始运行的前5分钟之内,每5秒钟连接一次,
当连接5分钟以后,如果还没有连接上,则等待若干时间后(等到占用的系统资源释放)
再连接5分钟...
这样不知道行不行?
 
干脆用用多线程来解决这个问题,方便
 
你连接失败以后就停止60秒以上就可以,我认为上面大家都说的是对的,不知道你
为什么总不接受大家的意见,60秒以后再连接了???
 
我其实是非常想搞清楚这个问题,
耽误了大家不少时间,真的是非常感谢大家!
 
如果一个程序同时使用TClientSocket 和 TServerSocket控件的时候,好像TClientSocket如果不能连接上Server端的时候,占用的listen端口就不会被释放,到最后还是会报10055错的
 
后退
顶部