socket长时间连接触发异常
向各位大神请教。
我做了一个网络采集程序,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;
我做了一个网络采集程序,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;
...全文
相关推荐
librtmp长时间直播socket连接断开的原因
本文分析了librtmp在长时间直播中因时间戳处理异常导致socket连接断开的问题。重点指出了扩展时间戳字段的解析错误,结合十六进制数据示例说明其触发机制,表明该问题是由于库对RTMP协议时间戳封装
socket异步和同步使用
这种模式下,程序会触发一个回调函数,当数据发送或接收完成后执行这个回调,这样可以避免线程被长时间占用。在描述中提到了“文件传输”,这是Socket应用的一个常见场景。
C# socket心跳
心跳机制在网络通信中起到关键作用,它是为了确保网络连接的稳定性和可靠性。在长时间无数据交换的情况下,网络连接可能会因为各种原因(如路由器或服务器的超时设置、网络拥塞等)而中断。
Android-MinaSocket一款基于Mina的Socket长连接库
- **心跳机制**:为了检测连接是否断开,通常需要设置心跳包,定时发送和接收,防止连接因长时间无数据传输而被网络中间设备关闭。
Socket-master.zip
此外,心跳包机制也可以帮助检测到连接丢失,并触发相应的事件。4.


网络通信/分布式开发
