DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: hxh57738897
今日帖子: 30
在线用户: 16
导航: 论坛 -> DELPHI技术 斑竹:liumazi,sephil  
作者:
男 qingyun (qingyun) ★☆☆☆☆ -
盒子活跃会员
2014/5/27 20:31:22
标题:
TclientSocket 尝试连接多次会报 缓冲区不足 浏览:3704
加入我的收藏
楼主: 10多年前就遇到这个问题,但是一直没有解决;
如下面这个帖子:
http://bbs.csdn.net/topics/70153564

我用了最彻底的方法:TclientSocket动态创建,如果一直连接服务端不成功,那么就freeandnil 后再全部重建,

但是时间长了,一样会报错;

后来做了一个最最彻底的方法,每次尝试连接1000次,如果再不连接成功,那么自动把整个exe程序重启;
----------------------------------------------
青云论坛
作者:
男 datm (dATM) ★☆☆☆☆ -
盒子活跃会员
2014/5/27 21:27:38
1楼: 10年了,你还不会用WinSock、API吗?
----------------------------------------------
-
作者:
男 bahamut8348 (leonna) ★☆☆☆☆ -
普通会员
2014/5/27 23:37:49
2楼: 你想做啥? 1000次? 有人重试那么多次的麽...

另外, tclientsocket是基于消息的. 在每次重连前, 你都必须确定内核对象被关闭了. 而且, 连接失败的话, 你要等待onerror出来才能进行下一次的连接尝试.
----------------------------------------------
--
作者:
男 qingyun (qingyun) ★☆☆☆☆ -
盒子活跃会员
2014/5/28 7:50:31
3楼: TclientSocket 使用简单 ,可以用非阻塞;
用WinSock、API?自己直接写最底层,没必要这样吧;
indy只有阻塞;

连接失败,确定了onerror之后才连接的;能想到的都想到了;
而且都已经freeandnil(TclientSocket) 在重建了;
----------------------------------------------
青云论坛
作者:
男 hs_kill (lzl_17948876) ★☆☆☆☆ -
普通会员
2014/5/28 8:53:29
4楼: ClientSocket自己的BUG 他free的时候没有释放Socket句柄, 你可以观察一下重复create100次, 句柄每次都是增加1的
free的时候用API吧句柄释放了

  Shutdown(_Socket.Socket.SocketHandle, SD_RECEIVE);
  _Socket.Socket.Close;
  WinSock.closesocket(_Socket.Socket.SocketHandle);
----------------------------------------------
http://www.cnblogs.com/lzl_17948876/
作者:
男 qingyun (qingyun) ★☆☆☆☆ -
盒子活跃会员
2014/10/21 17:47:28
5楼: 楼上兄弟的方法,我投入使用了;

还是不行;

在网上找到一段代码
(来自:
http://www.ylzx8.cn/windows/delphi/56337.html

------解决方案----------
在 ClientSocket 的OnLookup事件里,调整Socket的参数 (uses WinSock):
procedure TForm1.ClientSocket1Lookup(Sender: TObject;
Socket: TCustomWinSocket);
var
Bo_Dontlinger : BOOL;
begin
Bo_Dontlinger := True;
SetSockOpt(Socket.SocketHandle, SOL_SOCKET, SO_DONTLINGER, @Bo_Dontlinger, sizeof(BOOL));
end;

准备试试;
----------------------------------------------
青云论坛
作者:
男 qingyun (qingyun) ★☆☆☆☆ -
盒子活跃会员
2014/10/26 23:24:01
6楼: 找到一个第三方的控件:

http://uvc.sourceforge.net/ 

已经安装,打算以后用这个代替;

毕竟该控件一直在更新,bug和性能应该好过delphi6以后就不更新的自带的
tclientsocket 和 tserversocket;
----------------------------------------------
青云论坛
作者:
男 qingyun (qingyun) ★☆☆☆☆ -
盒子活跃会员
2014/10/27 12:09:04
7楼: http://bbs.csdn.net/topics/320178816
----------------------------------------------
青云论坛
作者:
男 qingyun (qingyun) ★☆☆☆☆ -
盒子活跃会员
2014/11/12 6:52:40
8楼: 使用了
在 ClientSocket 的OnLookup事件里,调整Socket的参数 (uses WinSock):
procedure TForm1.ClientSocket1Lookup(Sender: TObject;
Socket: TCustomWinSocket);
var
Bo_Dontlinger : BOOL;
begin
Bo_Dontlinger := True;
SetSockOpt(Socket.SocketHandle, SOL_SOCKET, SO_DONTLINGER, @Bo_Dontlinger, sizeof(BOOL));
end;

照样报错:

Windows socket error: 由于系统缓冲区空间不足或队列已满,不能执行套接字上的操作。 (10055), on API 'connect'


看来clinetsocket的顽疾搞不定了;


http://bbs.csdn.net/topics/70153564
----------------------------------------------
青云论坛
作者:
男 zmzj (zmzj) ★☆☆☆☆ -
盒子活跃会员
2014/11/12 9:22:36
9楼: 自己写个不就可以了
----------------------------------------------
-
作者:
男 jopher3 (樵夫的马六甲) ▲▲▲▲▲ -
普通会员
2014/11/12 9:41:35
10楼: 应该是哪里没处理好吧,
咱也用这个控件,在一个机器上连续不断地整,没发现这个错。

下面是一台机器上连续100万次访问服务器的测试,100%成功,没出错。
此帖子包含附件:
JPEG 图像
大小:520.4K
----------------------------------------------
樵夫的大马甲
作者:
男 jopher3 (樵夫的马六甲) ▲▲▲▲▲ -
普通会员
2014/11/12 9:44:09
11楼: 下面这个也是同一机器100万次访问服务器的测试,顺利完成。
此帖子包含附件:
JPEG 图像
大小:384.5K
----------------------------------------------
樵夫的大马甲
作者:
男 internetzs (internetzs) ★☆☆☆☆ -
盒子活跃会员
2014/11/12 13:52:14
12楼: 我用TClientSocket用得比较多, 知道如何解决这些问题

问题1: 
10多年前就遇到这个问题,但是一直没有解决;如下面这个帖子:
http://bbs.csdn.net/topics/70153564

这个问题, 是由于使用了Timer. 原因是TClientSocket每发起一个连接, 如何目标不存在, 则要超时20秒后,才释放socket资源. 如果你用Timer间隔设置低于20秒的话, 不断地调用ClientSocket1.Close时, 实际上socket还没真正关闭;要等到20秒后才能真正关闭, 这时你又调用 ClientSocket1.Open, 又会再新建连接资源. 反复就会累积很多socket资源没释放.
但如果连接能连通的情况, 上面的问题是不存在的.

问题2:
 4楼hs_kill说的没错, ClientSocket自己的BUG 他free的时候没有释放Socket句柄, 你可以观察一下重复create100次, 句柄每次都是增加1的
free的时候用API吧句柄释放了

这问题也是发生在连接不能连通的情况, 如果能通则问题也不存在的. 这应该算是delphi的bug
解决: 捕捉出错事件ClientError, 手工释放
procedure TForm1.ClientError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
  ErrorCode := 0;

  ClientSocket.Active:= False;
  ClientSocket.Socket.Close; // 如果无这行, 则资源不会释放, 多到系统的Socket句柄会溢出
 
end;
----------------------------------------------
-
作者:
男 internetzs (internetzs) ★☆☆☆☆ -
盒子活跃会员
2014/11/12 13:57:32
13楼: 上面10楼和11楼的测试是TCP能连通的情况, 这是不会有什么问题的.
问题是目标不能连通的情况, 而且要过一段时间才能看到问题, 最简单在任务管理中把句柄调出来看,会不断增长.
----------------------------------------------
-
作者:
男 err0rc0de (code) ▲▲▲▲△ -
普通会员
2014/11/12 14:11:19
14楼: 加一句Disconnect就好了。
原因很简单,在未连接成功时,active=true, close时并未将资源socketHandle释放。
算是个小BUG。

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  if ClientSocket1.Active then
  begin
    ClientSocket1.Socket.close;//Disconnect(ClientSocket1.Socket.SocketHandle);
    ClientSocket1.Close;
  end;
  ClientSocket1.Open;
  inc(i);
  caption:=intToStr(i);
end;
----------------------------------------------
-
作者:
男 internetzs (internetzs) ★☆☆☆☆ -
盒子活跃会员
2014/11/12 14:15:21
14楼: 再认真年了这贴:
10多年前就遇到这个问题,但是一直没有解决;如下面这个帖子:
http://bbs.csdn.net/topics/70153564

其实帖子下面的解决方法是OK的, qzxyd提出的问题, 其实下面DDGG等几位已经说出解决办法了, 和我的一样, 够清楚了, 只是DDGG提到要ClientSocket.Socket.close才能解决, 但qzxyd一直都误解成了ClientSocket.close, 这是不一样, 误认了, 问题就没法解决了.

别外xjlqlqlq也指出Timer时间不能设置太短, 楼主还是没听进去, 坚持Timer时间长短无关, 所以也是个原因.
----------------------------------------------
-
作者:
男 madwolf (林之白狼) ★☆☆☆☆ -
普通会员
2014/11/13 10:02:32
15楼: 不会吧,我加上了两句代码,确实没有出现泄漏的情况了,在Onclienterror中,并且会触发OncilentDisConnect
==========

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, System.Win.ScktComp, Vcl.StdCtrls, sLabel, sButton, sMemo, Vcl.ExtCtrls;

const
  WM_ReConnect  = WM_USER + $0001;
type
  TForm1 = class(TForm)
    ClientSocket1: TClientSocket;
    sButton1: TsButton;
    sLabel1: TsLabel;
    sMemo1: TsMemo;
    Timer1: TTimer;
    procedure sButton1Click(Sender: TObject);
    procedure ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
    procedure ClientSocket1Disconnect(Sender: TObject; Socket: TCustomWinSocket);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure OnWM_ReConnect(var Msg  : TMessage); message WM_ReConnect;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ClientSocket1Disconnect(Sender: TObject; Socket: TCustomWinSocket);
begin
  sMemo1.Lines.Add(DateTimeToStr(Now) + ': ClientSocket1Disconnect');
end;

procedure TForm1.ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
  ErrorCode := 0;
  sMemo1.Lines.Add(DateTimeToStr(Now) + ': ClientSocket1Error');
  ClientSocket1.Active:= False;
  ClientSocket1.Socket.Close; // 如果无这行, 则资源不会释放, 多到系统的Socket句柄会溢出
  PostMessage(Handle,WM_ReConnect,0,0);
end;

procedure TForm1.OnWM_ReConnect(var Msg: TMessage);
begin
  if not ClientSocket1.Socket.Connected then
  begin
      ClientSocket1.Host  := '127.0.0.1';
      ClientSocket1.Port  := 999;
      ClientSocket1.Open;
  end;
end;

procedure TForm1.sButton1Click(Sender: TObject);
begin
  PostMessage(Handle,WM_ReConnect,0,0);
end;

end.
此帖子包含附件:
JPEG 图像
大小:706.8K
----------------------------------------------
delphi加油!!
作者:
男 madwolf (林之白狼) ★☆☆☆☆ -
普通会员
2014/11/13 11:29:57
16楼: 运行了差不多2个小时了,也没有泄露
此帖子包含附件:
JPEG 图像
大小:426.0K
----------------------------------------------
delphi加油!!
作者:
男 internetzs (internetzs) ★☆☆☆☆ -
盒子活跃会员
2014/11/18 11:00:54
17楼: 楼上没用timer, 假如你在FormCreate中加入下面代码, 估计会看到句柄会增长

Timer1.Interval:= 1000;
Timer1.Ontimer := sButton1Click;
Timer1.Enable := true;
----------------------------------------------
-
作者:
男 internetzs (internetzs) ★☆☆☆☆ -
盒子活跃会员
2014/11/18 12:03:07
18楼: 上面, 其实更简单的方法, 手工不断地按Button1, 你就会发现Handle不断地增长.
----------------------------------------------
-
作者:
男 qingyun (qingyun) ★☆☆☆☆ -
盒子活跃会员
2014/11/20 22:37:25
19楼: 其实,我用的方法也很简单,和楼上alphacontrols 方法基本一致;
不够不确认到底真的解决没有:

1.如果尝试连接不上,那么自然会跳到onerr事件;
在该事件里加上:
      errcode:=0; //否则会弹出错误;
      socket.close;//这句话不清楚为什么要写,如果写了会触发onDisconnect事件;

2.这个才是最关键的:一定要等onerror事件触发之后,才能再次open;

所以在timer的时候搞一个锁变量,当open的时候,锁住;在连接成功或失败的时候,解锁;如果没有得到onerror 事件,就要一直等待下去,才能再次open;

这个确实有时短有时长,多则10多秒,少则1,2秒;

这毕竟是非阻塞的,所有在未得到成功或失败的响应之前不能再次open,道理上也是说的通的;



 madwolf (林之白狼)朋友提供的:


  PostMessage(Handle,WM_ReConnect,0,0);

也许确实能解决问题,不过感觉使用原始api,还是太“猛”了,会不会有其他并发症;
----------------------------------------------
青云论坛
作者:
男 madwolf (林之白狼) ★☆☆☆☆ -
普通会员
2014/11/20 23:05:02
20楼: 很简单的原理,使用TTimer,你设置间隔为1秒,到时间系统自动调用Ontimer事件,他又不管你连接上没连接上,所以每次Ontimer都会去打开,这样句柄自然会增加,直接在OnClientEroor中去触发这个事件,发个消息最简单了
----------------------------------------------
delphi加油!!
作者:
男 www123 (杨) ★☆☆☆☆ -
普通会员
2014/11/21 1:10:29
21楼: 很好,有技术含量
----------------------------------------------
-Courage is rightly esteemed the first of human qualities, because it is the quality which guarantees all others.
作者:
男 shloverxp (shloverxp) ★☆☆☆☆ -
禁用账号
2014/11/21 11:32:39
22楼: ……
被禁用帐号,帖子内容自动屏蔽!
……

----------------------------------------------
SPAM
作者:
男 www123 (杨) ★☆☆☆☆ -
普通会员
2014/11/23 1:15:54
23楼:
按照楼上几位大侠的嘱托,做了个简单的实验,结果证明,TclientSocke 可以持续运行,不过代价是内存会泄露,不管是用 timer 定时器,还是手动点击,也无论是多少秒,或者多少分钟后释放 socket, 只要是释放 socket 后,再 open, 这样反复的 open 或 close, 内存泄露就会一点点的增加,直到该应用的所能够占用的资源被耗尽。

汇报完毕。测试平台 WIN7 SP1 64 位 或 WIN 20008 R2 64 位.
----------------------------------------------
-Courage is rightly esteemed the first of human qualities, because it is the quality which guarantees all others.
作者:
男 qingyun (qingyun) ★☆☆☆☆ -
盒子活跃会员
2014/12/22 12:44:22
24楼: 楼上的,我开了一个程序,15个clientsocket,重连的时候,必须等socket onerror触发后释放; 连续运行了3天;都没问题;

win7 32位操作系统
----------------------------------------------
青云论坛
作者:
男 qingyun (qingyun) ★☆☆☆☆ -
盒子活跃会员
2015/9/11 16:43:03
25楼: 呵呵,我是楼主,
这是好久前发的帖子了,问题已经彻底解决了;
就是一句话: 在未收到onerror事件前不能重连;
或者说:onerror和重连必须1对1同步处理;

很多人都是TServerSocket/TClentSoceket不好;
推荐indy,但是indy因为阻塞的,个人喜欢非阻塞模式;

网上有人推荐:
http://sourceforge.net/projects/uvc/files/
不知道这个好在哪里;性能更高,更稳定;

还有rtc里面也有一个TCPSOCKET;

个人感觉应该差不多吧;


不知道手机andiroid下面,fmx环境下,
TServerSocket/TClentSoceket还能否使用了;
----------------------------------------------
青云论坛
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行125毫秒 RSS