我们在上一篇文章中介绍了Socket Server的开发,这一篇介绍Socket Client的开发。相对于服务端,客户端的启停更加灵活,更需要处理重连的问题。
带超时功能的连接
不知道为什么,经过这么多版的迭代,Socket连接依然不支持超时功能。如果网络无法连接,Socket连接会尝试连接30秒左右,这一般都不符号实际需求。
在最新版的Soekt中,加入了带CancellationToken参数的异步连接方法ConnectAsync,可以帮助我们实现连接超时功能。代码如下所示:
CancellationTokenSource cts = new CancellationTokenSource();
cts.CancelAfter(3000);//假设只尝试连接3秒
try
{
await ClientSocket.ConnectAsync(AddrEndPoint, cts.Token);
//连接成功
}
catch
{
//连接失败
}
断网重连的时机
如果网络本是好的,断开连接只是偶发性的因素引起,那么断开连接之后马上重连也未尝不可。但实际上断开连接时网络很可能不是好的。有可能物理链路断开了,有可能服务端宕机了,无论是哪种情况,我们都要等网络再次连通之后再去连接,否则就会消耗大量的资源。
一个比较好的方法是逐渐增加重连等待时间,在超过某个阈值后保持稳定。例如等待时间可以是一个这样的序列:1,2,3,5,10,20,30,50,50,50,50
检测连接断开
使用Socket.Connected去检测Socket是否连接是行不通的,可以使用下面的方法:
private bool IsConnected()
{
try
{
bool success1 = !InnerSocket.Poll(1000, SelectMode.SelectRead);
bool success2 = InnerSocket.Connected;
return success1 && success2;
}
catch
{
return false;
}
}
上面的方法实际上也是一个发送然后检查接收的过程,如果我们的程序本身就是不断发送,然后接收的,那没有必要通过上面的方法浪费资源。可以使用心跳机制,当服务端在一段时间内没有应答,即判定为断开连接,可以尝试重连。
关闭
如果需要关闭Socket,需要先断开连接,然后再关闭。由于每一步都会抛出异常,需要捕抓每一步产生的异常。
try
{
if (ClientSocket.Connected)
{
ClientSocket.Disconnect(false);
}
}
catch (Exception ex)
{
//
}
try
{
ClientSocket.Close();
}
catch (Exception ex)
{
//
}
ClientSocket = null;