最近在调试程序的时候,希望1秒钟调用一次 Socket.Receive() 来接收数据。
实际上,应该是说,如果没有数据到来,就是1秒钟一次,如果有数据到来,则收到数据后立即继续接收,然后继续是1秒钟接收一次。
C#的相关代码如下:
public bool ReadDataForMe(Socket sck, uint waitSec)
{
int rlen = 1;
DateTime ttStart = DateTime.Now;
//sck.ReceiveTimeout = 5;
sck.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, -300);
while (true)
{
try
{
PrintLog("start read socket.\n");
if (BaseTools.GetEclpseTime(ttStart, 0.4) >= waitSec)
{
break;
}
rlen = sck.Receive(m_bufRecv, 0, 1000, SocketFlags.None);
if (rlen == 0)
{
BaseTools.Sleep(100);
continue;
}
return true;
}
catch (IOException)
{
// 读取失败,原因:基础 System.Net.Sockets.Socket 被关闭。
return false;
}
catch (SocketException e)
{
if (e.ErrorCode == 10060)
// 超时的时候错误号码是10060
continue;
break;
}
catch (Exception e)
{
break;
}
}
return false;
}
// 如下调用
while(true)
{
if (ReadDataForMe(mySock, 1))
break;
}
其中BaseTools为一个基本工具库,自己封装的,这里用到了两个功能,一个是Sleep(),用于休息多长时间,另外一个是 GetEclpseTime() 用于获取指定的一个时间到当前时间的秒数,这样用于计算时间差。
另外还有一个函数 PrintLog() 用于在控制台打印字符串,其中添加了时间信息,代码如下:
public static void PrintLog(string s)
{
Console.WriteLine($"[{ DateTime.Now.ToString("HH:mm:ss.fff")}] {s}");
}
在每一次打印都添加了时间,精确到毫秒,这样方便对照打印时的时间。
测试方法就是连上服务器之后,服务器不发送数据,此客户端一直调用Receive()接口来收取数据。在每一次接收数据之前都加一行打印:start read socket.
以上为测试的环境情况。
下面测试主要是对函数开始的前几行的socket超时设置以及对超时时间的观察。
如上面的代码那样,设置超时时间为 -300,则打印间隔为500ms
如果改成3,则打印间隔为503ms