socket长时间连接触发异常

xrbaa 2020-03-25 04:47:59
向各位大神请教。
我做了一个网络采集程序,TCP连接,对端没有上电时,连接一定次数会报错误:
Windows socket error: 由于系统缓冲区空间不足或队列已满,不能执行套接字上的操作。 (10055), on API 'connect'。
线程也会死掉。
一种测试环境:我开68个采集线程,其中58个正常工作,10个对端没有上电,连接1625次报错。
另一种测试:我开66个采集线程,其中58个正常工作,有8个对端没有上电,约连接2035次报错(2034次2个,2035次5个,2036次1个)。
好像是没有释放掉资源,连接16250次以后就崩了。但是找不到问题在哪儿。
相关源代码如下:
procedure aDEV.ClientSocketConnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
//连接上
outinfo('端口连接成功!');
end;

procedure aDEV.ClientSocketDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
//连接失败
try
ClientSocket.Close;
except
RecordDataBaseEx(IntToStr(dev_ID) + ' SocketDisconnect中,Close失败。'); // 说明,这个没有触发,没有这条记录。
end;
RecordDataBaseEx(IntToStr(dev_ID) + ' Socket断开,状态置为:RUN_STATUS_EXCEPT_DISCONNECT。'); //这条语句会执行,有记录,这个事件处理函数退出后,就会触发系统异常,报出开头说的那个错误。
RunStatus := RUN_STATUS_NET_BAD;
end;

procedure aDEV.ClientSocketError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
ErrorCode :=0;
RunStatus := RUN_STATUS_NET_BAD;
end;

//定时器操作
procedure aDEV.tmrreadTimer(Sender: TObject);
begin
tmrread.Enabled :=False;
case RunStatus of
RUN_STATUS_READY: // 空闲
ConnectNet();
RUN_STATUS_WAIT_NET: // 等待网络
CheckNetTimeout(); // 如果连接成功,进入发送状态。
RUN_STATUS_NET_BAD: // 网络连接错误
ReConnectNetBefore;
RUN_STATUS_WAIT_FREE_NET:
begin
dec(iFreeCount);
if (iFreeCount < 0) then
RunStatus := RUN_STATUS_READY;
end;
//...........其它接收操作
end;
tmrread.Enabled := true;
end;

//连接到网络
procedure aDEV.ConnectNet();
begin
if ClientSocket = nil then
begin
// 如果套接字未创建,则先创建套接字。
CreatSocket;
SetParameter;
end;
//如果未连接则连接,连上则无须重连
if not ClientSocket.Active then
begin
try
ClientSocket.close;
finally
ClientSocket.Open;
end;
end;
RunStatus := RUN_STATUS_WAIT_NET;
end;
// 创建Socket控件
procedure aDEV.CreatSocket();
begin
ClientSocket := TClientSocket.Create(nil);
ClientSocket.OnRead := ClientSocketRead;
ClientSocket.OnConnect := ClientSocketConnect;
ClientSocket.OnConnecting := ClientSocketConnecting;
ClientSocket.OnDisconnect := ClientSocketDisconnect;
ClientSocket.OnError := ClientSocketError;
end;
// 设置参数
procedure aDEV.SetParameter();
begin
ClientSocket.Address := dev_IP;
ClientSocket.Port := dev_port;
ClientSocket.ClientType := ctNonBlocking;
end;

// 检查超时或者已经连上。
procedure aDEV.CheckNetTimeout();
begin
if ClientSocket.Active then
begin
RunStatus := RUN_STATUS_WAIT_SEND;
Exit;
end;
end;
// 网络连接错误,释放Socket,等等2秒。
procedure aDEV.ReConnectNetBefore();
begin
// 安全释放socket
ClientSocket.Free;
ClientSocket := nil;
iFreeCount := 2000 div dev_readtime; // 等待2秒。dev_readtime为定时器的
RunStatus := RUN_STATUS_WAIT_FREE_NET;
end;
...全文
102 点赞 收藏 2
写回复
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
xrbaa 2020-03-26
引用 1 楼 的回复:
procedure aDEV.ClientSocketError(Sender: TObject;
  Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
  var ErrorCode: Integer);
begin
  ErrorCode :=0;
  if ErrorEvent=eeConnect then
Socket.Close;
RunStatus := RUN_STATUS_NET_BAD;
end;


回复
weixin_39474058 2020-03-26
procedure aDEV.ClientSocketError(Sender: TObject;   Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;   var ErrorCode: Integer); begin   ErrorCode :=0;   if ErrorEvent=eeConnect then Socket.Close; RunStatus := RUN_STATUS_NET_BAD; end;
回复
相关推荐
发帖
网络通信/分布式开发
创建于2007-08-02

1573

社区成员

Delphi 网络通信/分布式开发
申请成为版主
帖子事件
创建了帖子
2020-03-25 04:47
社区公告
暂无公告