但碰到一个很奇怪的情况,就是当服务端和客户端A在已连接的情况下,如果有十几分钟或更长时间双方没有发送接收任何数据,
然后客户端A再次发送数据给服务端的话,服务端就接收不到了???
但更奇怪的是,如果另一个客户端B连接上服务端的时候,并发送数据给服务端后,好像又激活了服务端,然后这两个客户端分别收到了服务端发送过来各自对应的响应数据
难道异步通信中长时间不发送/接收数据会阻塞吗?代码如下,请兄弟姐妹们帮我分析下到底是什么原因造成的,万分感谢!!
//服务端
private Socket _sockSvr;
private const int _buffersize = 2048;
private DataStruct m_DpObj = null;//DataStruct 是个自定义的类
public class DataStruct
{
public Socket ClientSocket = null;
public string ID = string.Empty;
public byte[] RecvData = new byte[2048];
public int nReadBytesNums = 0;
}
public int Start()
{
StartListen();
_sockSvr.BeginAccept(new AsyncCallback(AcceptCallBack), _sockSvr);
return 1;
}
private void StartListen()
{
_sockSvr = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint iep = new IPEndPoint(IPAddress.Any, Port);
_sockSvr.Bind(iep);
_sockSvr.Listen(10);
}
private void AcceptCallBack(IAsyncResult ar)
{
Socket handler = (Socket)ar.AsyncState;
Socket _clientSock = handler.EndAccept(ar);
m_DpObj = new DataStruct ();
m_DpObj.ClientSocket = _clientSock;
m_DpObj.ID = GetClientIp(_clientSock);
_clientSock.BeginReceive(m_DpObj.RecvData, 0, _buffersize, SocketFlags.None, new AsyncCallback(ReceiveData), m_DpObj);
_sockSvr.BeginAccept(new AsyncCallback(AcceptCallBack), _sockSvr);
}
private void ReceiveData(IAsyncResult ar)
{
DataStruct ds= ar.AsyncState as DataStruct ;
Socket tempsocket = ds.ClientSocket;
ds.nReadBytesNums = ds.ClientSocket.EndReceive(ar);
if (ds.nReadBytesNums > 0)
{
//流程处理,忽略
}
ds= new DataStruct ();
ds.ClientSocket = tempsocket;
tempsocket.BeginReceive(ds.RecvData, 0, _buffersize, SocketFlags.None, new AsyncCallback(ReceiveData), ds);
Thread.Sleep(5);
}
6 个解决方案
#1
“客户端A再次发送数据给服务端的话,服务端就接收不到了”,
难道没有报错信息?
一般来说,如果数据量小,实时性要求低,不需要维持长连接,用完后就释放;
如果要维持长链路,如果数据实时性较低,
客户端就得有心跳机制来保证链路的活跃度
否则,即使server端没有超时清理,
好多网络设备也会自动清理非活跃的链路
难道没有报错信息?
一般来说,如果数据量小,实时性要求低,不需要维持长连接,用完后就释放;
如果要维持长链路,如果数据实时性较低,
客户端就得有心跳机制来保证链路的活跃度
否则,即使server端没有超时清理,
好多网络设备也会自动清理非活跃的链路
#2
没有异常,感觉socket还是维持连着的状态,因为终端始终也没断,只是发送消息给服务端服务端没有任何响应,但另一个客户端连接上后,好像服务端又被激活了一样,把要应答之前那个客户端的消息发出去了,给人的感觉像是BeginReceive被阻塞了一样
#3
如果有心跳维持就不会出现这个情况,就是在只连接但无任何交互的时候出现这个情况
#4
记录个日志(或者在 Debug.Print 打印日志),看看到底是 ds.nReadBytesNums = ds.ClientSocket.EndReceive(ar) 语句根本没执行,还是只是你的“流程处理,忽略”里边有问题。
把日志推送到具体的语句上,指明具体语言问题。不要自己根据“现象”拍着脑袋(而不动手),一叶障目。
把日志推送到具体的语句上,指明具体语言问题。不要自己根据“现象”拍着脑袋(而不动手),一叶障目。
#5
另外,就你的代码来说,所谓“流程处理,忽略”这里占用了 I/O 时间,是不好的。你或者把 tempsocket.BeginReceive... 语句放到他的前边(Sleep 5 是干什么的,你还要故意延迟程序执行?),或者把它异步处理而不要拖延 I/O。
#6
看你的描述,没有设置心跳包
搞心跳包就应该不会出问题 了
搞心跳包就应该不会出问题 了
#1
“客户端A再次发送数据给服务端的话,服务端就接收不到了”,
难道没有报错信息?
一般来说,如果数据量小,实时性要求低,不需要维持长连接,用完后就释放;
如果要维持长链路,如果数据实时性较低,
客户端就得有心跳机制来保证链路的活跃度
否则,即使server端没有超时清理,
好多网络设备也会自动清理非活跃的链路
难道没有报错信息?
一般来说,如果数据量小,实时性要求低,不需要维持长连接,用完后就释放;
如果要维持长链路,如果数据实时性较低,
客户端就得有心跳机制来保证链路的活跃度
否则,即使server端没有超时清理,
好多网络设备也会自动清理非活跃的链路
#2
没有异常,感觉socket还是维持连着的状态,因为终端始终也没断,只是发送消息给服务端服务端没有任何响应,但另一个客户端连接上后,好像服务端又被激活了一样,把要应答之前那个客户端的消息发出去了,给人的感觉像是BeginReceive被阻塞了一样
#3
如果有心跳维持就不会出现这个情况,就是在只连接但无任何交互的时候出现这个情况
#4
记录个日志(或者在 Debug.Print 打印日志),看看到底是 ds.nReadBytesNums = ds.ClientSocket.EndReceive(ar) 语句根本没执行,还是只是你的“流程处理,忽略”里边有问题。
把日志推送到具体的语句上,指明具体语言问题。不要自己根据“现象”拍着脑袋(而不动手),一叶障目。
把日志推送到具体的语句上,指明具体语言问题。不要自己根据“现象”拍着脑袋(而不动手),一叶障目。
#5
另外,就你的代码来说,所谓“流程处理,忽略”这里占用了 I/O 时间,是不好的。你或者把 tempsocket.BeginReceive... 语句放到他的前边(Sleep 5 是干什么的,你还要故意延迟程序执行?),或者把它异步处理而不要拖延 I/O。
#6
看你的描述,没有设置心跳包
搞心跳包就应该不会出问题 了
搞心跳包就应该不会出问题 了