TClientSocket不断尝试与TServerSocket连接,运行一段时间后的问题!

DDGG 2002-05-14 07:14:25
运行环境:WindowsXP + Delphi 6.0

要求:使用一个TClientSocket尝试与尚未运行的TServerSocket服务端应用程序连接,力求在TServerSocket运行后尽快与之建立连接并通信,因此使用一个TTimer定时为1秒不断尝试连接。

注意:TServerSocket平时是关闭的,很少开启,而TClientSocket要在其开启后尽最大努力尽快与之连接。

另外:TClientSocket和TServerSocket均采用ctNonBlocking(非阻塞方式)。

在TClientSocket的OnError事件中屏蔽连接失败错误:
procedure TForm1.ClientSocket1Error(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
ErrorCode := 0;
end;

定时器中代码如下:
procedure TFrom1.Timer1Timer(Sender: TObject);
begin
if not ClientSocket1.Active then ClientSocket1.Active := True;
end;

结果:TServerSocket服务端应用程序启动时,TClientSocket能正常与TServerSocket连接,但如果TClientSocket运行一段时间后仍未启动TServerSocket服务器(大约10分钟),TClientSocket应用程序就会出错!

错误为:Project BNTester.exe raised exception class ESocketError with message 'Windows socket error: 当该操作在进行中,由于保持活动的操作检测到一个故障,该连接中断。(10055), on API 'connect". Process stopped. Use Step or Run to continue.

继续运行还会引发另一个错误:Project BNTester.exe raised exception class ESocketError with message 'Windows socket error: 提供的文件句柄无效。(10022), on API 'WSACancelASyncRequest"". Process stopped. Use Step or Run to continue.

我初步分析是由于Socket句柄资源用尽导致的,有什么方法可以解决?
...全文
1228 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
sunhuiNO1 2002-05-15
  • 打赏
  • 举报
回复
用一个单独的线程连接,这个线程用阻塞方式。就不会出现你说的问题,
lizhenjia 2002-05-15
  • 打赏
  • 举报
回复
开始->程序->delphi6->help->ms sdk help->windows socket 2 reference
然后键入 error codes
DDGG 2002-05-15
  • 打赏
  • 举报
回复
To: lizhenjia(暴雪)

谢谢你!
DDGG 2002-05-14
  • 打赏
  • 举报
回复
TO: lizhenjia(暴雪)

> 10055错误:
> WSAENOBUFS
>
> (10055)
>
> No buffer space available.
>
> An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full.

你在哪里找到指定错误号的解释的?我怎么在Help里找不到?
DDGG 2002-05-14
  • 打赏
  • 举报
回复
To: 猛禽

>直至连上后再断开,改回NonBlocking方式
这么做有点牵强,如果一连接上,Server就要主动向Client发送数据呢?

你的意思是说如果两端都用Blocking方式就没有问题了?
猛禽 2002-05-14
  • 打赏
  • 举报
回复
最简单的解决办法是将ClientSocket改用Blocking方式试连,
直至连上后再断开,改回NonBlocking方式
lvloj 2002-05-14
  • 打赏
  • 举报
回复

procedure TFrom1.Timer1Timer(Sender: TObject);
begin
try
clientsocket.open;
Timer1.Enable := False;
except
ClientSocket.Close;
end;
end;

ClientSocketOnDisConnect事件:
Timer1.Enable := True;
DDGG 2002-05-14
  • 打赏
  • 举报
回复
To: hieefxz(凡人邪真)

lizhenjia(暴雪)说的没错。
DDGG 2002-05-14
  • 打赏
  • 举报
回复
To: plainsong(轻风)

你说的方法我试过的,使用Timer还是使用线程都可以(Timer本身就是一个线程)。我是这么做的:在OnTimer事件里再多判断一个条件(即本次连接是否完成):
procedure TFrom1.Timer1Timer(Sender: TObject);
begin
if not ClientSocket1.Active and not F_Connecting then
begin
F_Connecting := True;
ClientSocket1.Active := True;
end;
end;

在ClientSocket1的OnError和OnDisconnect事件中增加一行:
F_Connecting := False; // 本次连接结束,可以再次进行连接。

结果还是一样的,也许如同“Thumb168(大母指)”所说,只要TClientSocket未消亡,它所用过的SocketHandle就不会释放?
DDGG 2002-05-14
  • 打赏
  • 举报
回复
To: plainsong(轻风)

你说的方法我试过的,使用Timer还是使用线程都可以(Timer本身就是一个线程)。我是这么做的:在OnTimer事件里再多判断一个条件(即本次连接是否完成):
procedure TFrom1.Timer1Timer(Sender: TObject);
begin
if not ClientSocket1.Active and not F_Connecting then
begin
F_Connecting := True;
ClientSocket1.Active := True;
end;
end;

在ClientSocket1的OnError和OnDisconnect事件中增加一行:
F_Connecting := False; // 本次连接结束,可以再次进行连接。

结果还是一样的,也许如同“Thumb168(大母指)”所说,只要TClientSocket未消亡,它所用过的SocketHandle就不会释放?
lizhenjia 2002-05-14
  • 打赏
  • 举报
回复
to hieefxz(凡人邪真)
你的方法是不行的,这种在onerror事件中和在ontimer中 尝试重连接又有何区别呢?只是你连接的次数少而已,我早就是过了,你可以把server关掉,然后在onerror事件中如果errorcode=10061就不断重联,30--70次保证程序down掉!
hieefxz 2002-05-14
  • 打赏
  • 举报
回复
方法太土了。不用Timer控件。在OnError事件里处理,当你连接时如果失败返回错误,这时进行处理:
form1.ContinueConnect
begin
clientsocket.active:=false;
try
clientsocket.address:='127.0.0.1';
clientsocket.port:=6677;
clientsocket.active:=true;
except
abort;
end;
end;
该过程在错误处理中调用,我试过了是可以的。
就是server关闭时,
要在Disconnetion事件中再进行处理。
riddler 2002-05-14
  • 打赏
  • 举报
回复
关注
短歌如风 2002-05-14
  • 打赏
  • 举报
回复
不要用Timer控件,改用线程去做.
在线程里循环进行连接,每次连接前等待一个事件,这个事件由TClientSocket.OnError中的代码触发,直到连接成功或线程被终止.以保证每次连接时,上一次的连接已经断开.

____ ____
\ p \ / g /
\ l \_/ n /
\ a o /
\ i s /
\ n /
\_/
DDGG 2002-05-14
  • 打赏
  • 举报
回复
To: Thumb168(大母指)
为什么我认为是Socket句柄(SocketHandle)资源用尽的问题呢?因为我曾在OnTimer事件里监视过ClientSocket1.Socket.SocketHandle 。
procedure TFrom1.Timer1Timer(Sender: TObject);
begin
if not ClientSocket1.Active then ClientSocket1.Active := True;
// 曾在此处以写Log日志文件方式监视过程序运行过程
// 中ClientSocket1.Socket.SocketHandle,发现此值每次总会以+2~+8
// 速度递增,最后达到3万多的时候就是程序出错之时。
end;


在Timer触发事件里创建TClientSocket、进行连接,还要释放,再退出OnTimer?这好像有点奇怪,因为连接成功与否要通过TClientSocket的OnConnect、OnError事件被触发来得知的啊!

你的意思是一旦TClientSocket的实例被释放,它所使用过的资源(比如SocketHandle)也就还给系统可以重新分配使用了?
lizhenjia 2002-05-14
  • 打赏
  • 举报
回复
10055错误:
WSAENOBUFS

(10055)

No buffer space available.

An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full.
lizhenjia 2002-05-14
  • 打赏
  • 举报
回复
这个问题我也曾经遇到过,强烈关注解决办法,不过最好的办法就是不要这么无限制地连接下去
因为出现这种问题的原因是客户机的缓冲区或者队列满了,系统缺乏资源,如果在连接下去windows离down就不远了.纤细请查看sdk帮助.
Thumb168 2002-05-14
  • 打赏
  • 举报
回复
你的推测不下确,你可以这样 试一下,在时间触发事件中动态申请一个TClientsocket来测试联接,如果能服务器启动了,哪么再调用静态的TClientSocket与之相联接。当然,别忘记要自己接管处理一些错误信息。好了试一下吧,应该可以的。也别忘记在时间触发事件结束时释放动态的TClientSocket

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧