问题描述
两个C#应用,一个作为服务端Server,另一个作为客户端Client,客户端打开一个Udp端口,循环接收数据;服务端开启后向客户端发送指令,当服务端出现异常时关闭了服务端的UdpClient,此时客户端卡死在_client.ReceiveAsync(),无法再接收到消息。
客户端代码:
try
{
var cts = new CancellationTokenSource();
var client = new UdpClient(new IPEndPoint(IPAddress.Any, 10000));
Task.Run(async () =>
{
while (true)
{
await Task.Delay(100, cts.Token).ConfigureAwait(false);
if (_client != null && _client.Available != 0)
{
if(cts.Token.IsCancellationRequested) break;
var res = await _client.ReceiveAsync().ConfigureAwait(false);
if (res.Buffer != null && res.Buffer.Length > 0)
{
Console.WriteLine(res.Buffer);
}
}
}
}, cts.Token);
}
catch(Exception e)
{
}
服务端UdpClient关闭后,客户端catch陷入无限等待,且无法捕获到异常,服务端重启后也无法再次接收服务端消息。
解决方案:服务端断开后,客户端会收到远程主机关闭连接的异常,将异常捕获移动到内部,并捕获SocketException异常,当捕获到的异常代码为ConnectionReset时,表示远程主机关闭,不做处理即可,下次服务端重启后可正常连接。
var cts = new CancellationTokenSource();
var client = new UdpClient(new IPEndPoint(IPAddress.Any, 10000));
Task.Run(async () =>
{
while (true)
{
await Task.Delay(100, cts.Token).ConfigureAwait(false);
if (_client != null && _client.Available != 0)
{
if(cts.Token.IsCancellationRequested) break;
try
{
var res = await _client.ReceiveAsync().ConfigureAwait(false);
if (res.Buffer != null && res.Buffer.Length > 0)
{
Console.WriteLine(res.Buffer);
}
}
catch (SocketException ex)
{
if(ex.SocketErrorCode == SocketError.ConnectionReset)
{
//远程主机关闭连接
}
// 处理接收超时或其他异常
else Console.WriteLine($"Socket exception: {ex.Message}");
}
}
}
}, cts.Token);
标签:ReceiveAsync,UDP,cts,C#,res,Buffer,client,服务端,客户端
From: https://www.cnblogs.com/zp1207/p/18471425