有关socket异常处理的问题(100分)

  • 主题发起人 主题发起人 cavalise
  • 开始时间 开始时间
C

cavalise

Unregistered / Unconfirmed
GUEST, unregistred user!
本人采用clientsocket 和serversocket作了一个通讯的程序,客户端在连服务器的时候如果服务器开着,是正常的,但是服务器程序关了,就会出现异常,在客户端的onerror事件里写入errorcode:0;可以屏蔽错误,但是如果时间长了就会导致系统功能不正常,好象是站了什么缓冲区(症状是ftp命令用不了,显示:ftp>bind:缓冲空间不受支持,然后浏览器也不能用了,最后是程序里的手动复位点击,包错:socket缓冲区或队列已满....)
我估计就是每次连服务器连不上,有些过程信息就驻留缓冲区了,不能在每次清掉的话,总会堆满,这时就出问题了.
请教各位富翁:如何做才能避免这个问题发生?(我的程序每隔10秒判断是否连上,如果每连上,就连接一次,大约2小时左右,ftp就不能正常工作了,只要程序一退出,就一切恢复正常,另外我尝试在client的error和disconnect事件里,加入clinetsocket.socket.close;会报错
Estackoverflow)本人期待各位的答复,看过请留言,哪怕是一点思路也好,叩谢!
 
如果是98的话可能会出现这种情况,2k好像不会有。建议每次连接超时后(errorcode=10061)
先关闭clientsocket.close;再尝试连接。
 
其实是这样的,你的clientsocket一定在serversocket断开以后还在继续发送消息,所以就产生了错误,而通讯过程中产生的错误异常又被你用errorcode:0屏蔽了,当事实错误累计到一定程度的时候,操作系统的稳定性就会降低,因为其实你用的还是底层的方式在通讯,无非是VCL已经帮你封装好了,你不需要看到而已,但是操作系统的稳定性,因为你的大量错误还是会体现的,所以Win2000比较稳定就是这个缘故,因为他的自我保护更加好一些,你用的这个errorcode:0方法其实也没有什么错,但是你最好在发送消息以前先判断连接是否正常,然后再发送,如果连接已经断开(网络通讯由于其线路的复杂性,有好多的突发状况是无法估计的),请重新连接,并且在界面上提示连接已经断开。因为TCP/IP通讯其实是相当稳定的一种通讯方式,在双方握手以后,一般情况下是不会出现错误的,如果出现了错误的话,你其实也可以知道,你可以提取这个错误,然后再将错误清0 --- errorcode:0。

if ClientSocket1.Socket.Connected=True then
ClientSocket1.Socket.SendText(STX+'LE|DA'+DA+'|TI'+TI+'|'+ETX);
 
上面的TCP/IP通讯错误,你一定提取出来,然后显示,比如楼上说的,errorcode=10061你可以把他显示在主界面上,然后提示:通讯异常超时,错误代码:10061等信息,同样你在使用QQ的时候如果把网线拔了,你也可以看到QQ的网络错误的消息,这点你也可以借鉴。
 
这个最好通过哪个错误事件的类型来判断是什么错误,这样要容易一些,
错误代码太多了,不好区分
 
天使屁屁猪:我并没发送数据,只有在触发了connect事件后(我在里面设了标志),标志变为真时,才发送数据的.另外我刚做的测试,在我试图连接而连不上的时候,通过系统监控,我发现句柄数以及页面错误会略有增加,不知道这是不是就是原因.
请各位继续发言,我现在一头雾水.(如果我停掉那个自动连接的时钟,一切正常,我想问题应该就在这上面,或者是在error的事件代码里,不知道我这么想对不对)
一下是部分代码:
时钟里的一部分:
if (dq='宜昌') and (sflj='y') and (ycf.Active = false) then
begin
yc:=true;
ycf.Address:=ip;
try ycf.Active:=true; except ycf.close; end;
end;
error里的代码:
begin
errorcode:=0;
ycf.Close ;
end;
 
张无忌:你好象经常回答别人问题,真是个热心的大富翁.
谁说富翁都无人情了!?
建议大家都留个联系方式,方便大家交流,你认为呢?
我的qq:915381
msn:cavalise@hotmail.com
 
chenxz:问题确实如你所说,就是10061,连接超时,但是我在error事件里写了clientsocket.close;还是没有用啊.请继续发言,谢谢
 
你的这个问题以前回答过很多次了,你连接失败关闭连接以后以后要sleep()一会儿
再连接
 
张无忌:我的时钟是10秒才触发一次的啊,难道还不够吗?:)
请明示,恕在下愚钝
 
你在Timer的TClientSocket的打开之前前判断TClientSocket是否是打开的,
如果是打开的就不用管他,继续,我建议你把时钟改成30秒比较好,
 
代码太少了,给多一点大家来看看这样可能好一些。上面的程序好像没有问题。
 
张无忌:if (dq='宜昌') and (sflj='y') and (ycf.Active = false) then
begin
yc:=true;
ycf.Address:=ip;
try ycf.Active:=true; except ycf.close; end;
end;

其中 and (ycf.Active = false) 应该就是你说的那个判断了吧.昨天改为1分钟触发一次,今天早上来看,句柄到了4k多了,导致ftp和浏览器都用不了,症状一样.
 
天使屁屁猪:其实对每个连接来说就是这么点,只不过有13个地区的节点要连,而且每个地方是2条线,一收一发的.所以每次时钟触发的时候错误增量比较大.
另外这里并不涉及read和disconnect事件,因为这些根本还没触发,所以我想问题就在以上这些代码里,只不过我不知道还要加什么条件或者是执行什么其他操作.
 
以下是我测试的代码:
implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
clientsocket1.Open ;
end;

procedure TForm1.ClientSocket1Error(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
errorcode:=0;
end;
ClientSocket1的属性都赋了值
请大家看一下是不是每按一次button句柄数就会增加的.
 
procedure TForm1.ClientSocket1Error(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
errorcode:=0;
if ErrorEvent=ssConnect(手写的,可能有问题) then
ClientSocket.Active:=False;//这样才行,要关闭连接
end;
 
张无忌:ssConnect我不知道怎么写正确,但是我写
procedure TForm1.ClientSocket1Error(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
errorcode:=0;
//if ErrorEvent=ssConnect then
ClientSocket1.Active:=False;//这样才行,要关闭连接

end;
句柄还是增加了啊,你可以自己看看,谢谢了.
在任务管理器里看,查看里把选择列的句柄数打上钩就可以看到了.
 
由于ClientSocket.Active:=False的时候socket没有立刻关闭
需要发4个数据包和服务器进行通讯才能关闭,所以要等待一会
才真正释放资源.所以你说的HANDLE增加是正常的,如果想
Active=False的时候关闭需要使用setsockopt设置不进入半等
待状态...
 
张无忌:还请张教主明示。:)
setsockopt,这个函数我看到过,不知道怎么用啊。
 
一般情况下没有必要关闭socket的半等待状态,你只要保证不要太快的打开socket就可以了,每次打开socket的时间间隔长一点,比如60秒...基本上可以避免你出现的问题
 
后退
顶部