1.一个udp客户端,在启动时,用Thread线程开一个Receive循环接收数据
2.之后,开一个Factory.Run线程,每秒一次读实时数据
3.响应用户操作,开一个线程下发
问题:运行二天后,Receive似乎一直忙于处理读实时数据,响应用户下发指令很快;但在Receive时,有时需几分钟才在Receve中处理下发返回的数据
1.一个udp客户端,在启动时,用Thread线程开一个Receive循环接收数据
2.之后,开一个Factory.Run线程,每秒一次读实时数据
3.响应用户操作,开一个线程下发
问题:运行二天后,Receive似乎一直忙于处理读实时数据,响应用户下发指令很快;但在Receive时,有时需几分钟才在Receve中处理下发返回的数据
async task udp接收() //这里我随手从现有代码里包个方法,有些传入参数我就不写了,自己看明白了就好
{
while (!token.IsCancellationRequested)
{
try
{
using (var m = MemoryPool<byte>.Shared.Rent(65507)) //udp最大封包字节是65507,我从字节池申请一块字节来用
{
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 0);
//其实无需定时1s,await的意思是有数据来就收,没数据来就等着
//也就是对方发给你了你就收,没发不理会
//我当然不知道你们“取”的协议是啥,如果“取”是向对方发一条指令,你顶多是定时发指令,而收嘛就这里,不在定时器里
var r = await _socket.ReceiveFromAsync(m.Memory, SocketFlags.None, endPoint, token);
// _logger.LogInformation("收到-----------");
var buffer = m.Memory.Slice(0, r.ReceivedBytes) //你收到数据
var rip = r.RemoteEndPoint;//远方ip
var str = UTF8Encoding.ASCII.GetString(buffer.Span); //这个是打印字符串,当然你自己的协议怎么解析是另外一件事情,我这里只是如实打印
}
}
catch (Exception e)
{
}
}
}
ps:虽然这代码我是用socket收的,不过用updclient其实是一样的代码,uppclient同样有异步接收方法ReceiveAsync
其实现在代码,我们其实不特别强调线程了。await足以
特别说明;对于网络IO来说这代码其实没有线程,并不是有 async task await就有线程。这里只是一个单纯的异步IO,你await的只是等待网卡驱动从网络接收数据(他收到了“回调”给你,或者说那是iocp完成端口异步唤起处理),而非你await一个线程处理
另外在补充一下,收了数据后怎么搞。
收到数据后,请不要做复杂的操作。对udp来说封包没有要拆包一类操作,所以大部分情况下我们认为收到一包就是一包(使用udp的大多数也不发大于上面规定的65507的数据,所以常规情况我们认为无需进行拆包操作)
所以收到数据以后请直接发布到Rx.net 或者 Channel这种生产/消费队列里。你收到了,生产了就行了
至于外面怎么消费,你不要管
在另外说一下,udp嘛无连接,偶尔丢包,偶尔乱序,偶尔延迟很正常,因为udp本身就是这样设计的。不存在tcp那种你发了,我没收到的或者你收迟了这种说法,对于使用udp的(还没有设计验证,重发,包序的)我们可以理直气壮的说“我就没收到,我就收乱了,我就收迟了”怎么拉,udp原本就如此,你任何资料任何书上都这么写的