TClientSocket控件的问题(怀疑是bug)(300分)

J

jinchi

Unregistered / Unconfirmed
GUEST, unregistred user!
--------------------------------------------------------------------------
问题:
用一个clientsocket控件连接一个已经在网络上的ip或者不在网上的ip,但对方
主机没有开.那么必然是连不上的,只要你在clientsocket的error事件中:ErrorCode:=0
,那么就不会出现错误报警框.
理论上是这样,但若你连不上后再次打开,连个100-200次,就会发现,出现非法报警框.
socket错误:1055(错误代码的意义是:缓冲区不足).并且这种错误即使你加上try..except
依然没法子避免.
故怀疑这是clientsocket的一个bug,可能需要修改这个控件对应的单元文件.但....
偶不会,呜呜呜呜.那位研究研究?研究出来可否告知?
--------------------------------------------------------------------------------
必须用的原因:
因为偶socketserver端的机器的对应的socket服务应用程序未必开着或者网线断了.
那么偶只能用clientsocket来连接试试,看能否连上.因为客户端是一个实时的通讯,中断了
只能连接着尝试.
那位有好的方法替换的话也可以.偶尝试了各种方法如:echo等.ping不行,不能知道
对方的server socket对应端口是否打开.
-------------------------------------------------------------------------------
说明:
1:分若不够另外加(偶另外开个问题表你来拿分,呵呵
2:若真是bug,可能需要修改这个控件的源码.修改源码的兄弟偶一定另外加分(你开价)
3:若能提供满意的替换方法(不要告诉我换ics或者indy等,呜呜呜,时间不够)
--------------------------------------------------------------------------
测试代码:(运行个一袋烟的功夫就够了,嘿嘿)
unit testsck;//测试tclientsocket连接错误,
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp, ExtCtrls, StdCtrls;
type
TForm1 = class(TForm)
ClientSocket1: TClientSocket; //连接在网上的电脑对应的ip(或者自己的电脑ip),但对方没有开对应的socketserver服务
//port:11,当然随便你,只要不是0就行
Timer1: TTimer; //定时器,每5s(30s也可),检测clientsocket打开否?没打开则打开.
Memo1: TMemo; //显示当前socket连接状况.
ClientSocket2: TClientSocket;//连接不在网上的ip. port:12或者任意(非0)
procedure ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
procedure Timer1Timer(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure ClientSocket2Error(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
Sck1OpenCount,Sck2OpenCount:Integer;//两个clientsocket连接次数统计.
implementation
{$R *.dfm}
procedure TForm1.ClientSocket1Error(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
memo1.Lines.Add('clientsocket1第:'+IntToStr(Sck1OpenCount)+'次闭。'+'错误代码'+IntToStr(ErrorCode));
ErrorCode:=0;
if ClientSocket1.Active=True then
ClientSocket1.Active:=False;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
if memo1.Lines.Count>100 then
memo1.Clear;
if ClientSocket1.Active=False then
begin
ClientSocket1.Active:=True;
Sck1OpenCount:=Sck1OpenCount+1;
memo1.Lines.Add('clientsocket1第:'+IntToStr(Sck1OpenCount)+'次打开');
end;
if ClientSocket2.Active=False then
begin
ClientSocket2.Active:=True;
Sck2OpenCount:=Sck2OpenCount+1;
memo1.Lines.Add('clientsocket2第:'+IntToStr(Sck2OpenCount)+'次打开');
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Sck1OpenCount:=0;
Sck2OpenCount:=0;
Timer1.interval:=5000;
Timer1.enabled:=true;
end;
procedure TForm1.ClientSocket2Error(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
memo1.Lines.Add('clientsocket2第:'+IntToStr(Sck2OpenCount)+'次闭。'+'错误代码'+IntToStr(ErrorCode));
ErrorCode:=0;
if ClientSocket1.Active=True then
ClientSocket1.Active:=False;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
if ClientSocket1.Active=True then
ClientSocket1.Active:=False;
if ClientSocket2.Active=True then
ClientSocket2.Active:=False;
end;
end.
 
老大们,怎么没有人理偶,呜呜呜,难道分还不够多................
这个程序很简单,拿来测试一把就发现了这个问题了.绝对是值得关注的一个问题牙?
希望各位捧捧场,测试一把,然后共同关注一下.
 
我以前用的时候也发现这个,没仔细试,具体是150-160次,后来没办法,在尝试150后,
就不试图连接了,要求重启后再连接。。。 :( 今天来学习。我们同命相连啊。。。
 
靠!重启!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!口吐白沫绝倒在地......
不能阿老大,偶没事一天来个几次重启,这个项目的公司还不砍死我,呵呵
 
我不是让你重启啊,我是说我的程序是这么处理的呀,因为我的客户程序本身还可以单独工作呀,
和主机连接起来就可以接受主机的指令,我来也是学习的,别骂我呀,:(
 
我也被 Delphi 的 Socket 搞惨了, 还在奋斗

你在两次连接之间加些 延迟(如 Sleep 或 Delay) 如何
 
别用TClientSocket了,用Indy控件试试。Delphi6附送的。
 
从 Delphi3 起我就发现 TClientSocket 有 Bug,还改了 D3/D4的源码
现在客户端一直用 ICS 的 TWSocket ,挺稳定的:)
 
TO:koyochen
延时一点用处都没有。我试过。
 
我测试了一下,好象没问题啊。我系统是win2k。
 
倒了!难道是系统的问题?偶是win98.
最好98下解决,因为2K看门狗不能用。
 
to truecat:
你说的重启是什么意思?你那个ClientSocket的应用程序么?怎么重启?呵呵
 
用TClientSocket的阻塞模式,最好在线程中写连接的事件(不然界面会死的很难看)
proceudure TThreadMy.Execute;
var
Socket: TClientSocket;
begin
//init Socket
Socket.ClientType := clBlock;
while not Socket.Active and not Terminated do
begin
try
Socket.Open;
except
end;
Sleep(1000);
if Socket.Active then
PostMessage(MainForm.Handle, WM_SocketActive, 0, 0);
end;
Socket.Free;
end;
 
偶再看看ics的TWsocket,若是一点问题没有的话,偶打算用它。
TO 轻松虎:
可否发送给我一个功能比较全的例子,不是ICS自带的哪个DEMO。
最好不要那种你项目的大程序,而是功能完善的测试程序(不要放进EXE,太大)

功能包括:连接,错误处理,发送,接收,其中关键是错误处理。
另外,发送接收是不是有几种方式,如同TCLIENTSOCKET的SENDTEXT。。。等。
另外注意平台是:win98

偶也顺便看看这个控件,呵呵。
偶的EMAIL:lixiuliang@iipc.zju.edu.cn,谢谢。可否尽快发给我,最好关键地方能有注释。
并且把一些需要注意的地方写一下 ,呵呵
 
NonBlocking是比较麻烦,你最好用Blocking方式来试,它会在open时等待,连不上会出异常
 
建议使用UDP,然后在自己的通讯协议中增加握手信号。
使用UDP不会因为连接不上而报错误,当接收方收到后,解析如果是握手信号则返回一信号,
发送方接收到接收方发送回的握手信号,则可认为连接正常了。
CS和SS连接时确实存在上述的问题,我记得是150多次,不到160次准死!
 
to jichi:
哇,这么高要求,哪有时间专门写啊。
不过呢,刚才仔细看过你的问题了,这问题我几年前碰到过。。。
你可以把 OnError 事件这么写:
(uses 里加上 WinSock)

procedure TForm1.ClientSocket1Error(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
ErrorCode:=0;
ClientSocket1.Active:=False;
ClientSocket1.Socket.Close;
Shutdown(ClientSocket1.Socket.SocketHandle,0);
end;

应该就行了。Active := false 没有真正释放资源。
我印象中 ClintSocket 以前还有别的 bug,比如原来发现断开重连后第一个数据包经常有错等等,
后来我索性改用 TWSocket 到现在。不知道现在 D6 里的 ClientSocket 改好了没有。

ICS TWSocket 简介:
Windows消息驱动(跟 ClientSocket 同类),支持 TCP /UDP,支持 socks 代理
发送有 Sendstr SendText(采用string 参数,两者一样),RecieveStr方法
还支持换行符分包形式,对于自定义的非二进制的请求应答协议非常方便(取个完整的包,不用自己收集,等待,断包)。。。
关键是 bug 少,稳定,没发现内存泄漏等问题,用在客户端挺好,
ICS的服务端写的一般般。
 
顶部