我最近开始研究套接字编程并编写了一个简单的异步tcp服务器,可以从各个客户端发送接收就好了。这是它的简化代码:
//accpet loop
while (true)
{
var client = await listener.AcceptTcpClientAsync();
new AppClient(client).Start();
}
// and here is the start method in AppClient class
public async void Start()
{
/// TcpClient is a class property which is in scope of this method
using (var stream = TcpClient.GetStream())
{
string message = string.Empty;
byte[] buffer = new byte[1000];
int bytesRead = 0;
while (true)
{
try
{
bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
break;
}
// decode simple text message
message += Encoding.UTF8.GetString(buffer, 0, bytesRead);
}
}
}
它以单线程方式处理数千个连接但是 令我不安的是,无论我如何摧毁客户端(查杀过程和......), ReadAsync 方法立即抛出异常,这与我的想法基本上相冲突。 (据我所知,在tcp中检测断开的套接字应该不那么容易)
我做错了什么?答案 0 :(得分:1)
您应该将.ReadAsync()
与cancellationToken一起使用。然后更改循环以检查标记值。当您要杀死客户端时,您会发信号通知令牌。
同时检查变量bytesRead
。如果它返回0
,则连接刚刚关闭。
答案 1 :(得分:1)
让我心烦的是,无论我如何摧毁客户端 (查杀进程和...)ReadAsync方法立即抛出一个 例外
欢迎使用网络(套接字)编程。您可以对这些异常做好准备,因为在这些类型的应用程序中遇到异常是很常见的。这种行为是设计使然。
应该在最终用户得到好消息的情况下开发你的应用程序,而不是异常消息。
... ReadAsync方法立即抛出异常 基本上与我的想法发生冲突(据我读过检测 在tcp中断开连接的套接字应该不那么容易)
原因是:
TcpClient.Connected Property
获取上次I / O操作时Client套接字的连接状态。当它返回false时,客户端套接字从未连接,或者不再连接。
由于Connected属性仅反映最近一次操作时的连接状态,因此您应尝试发送或接收消息以确定当前状态。 消息发送失败后,此属性不再返回true。
请注意,此行为是设计使然。您无法可靠地测试连接状态,因为在测试和发送/接收之间的时间内,连接可能已丢失。您的代码应该假定套接字已连接,并正常处理失败的传输。
答案 2 :(得分:0)
它不是“检测”断开连接,它是trhows和exception,因为.ReadAsync
一直试图获取是否有可读取的数据,如果有写入缓冲区,如果数据长度==缓冲区长度然后结束功能。所有这些步骤(可能还有更多)涉及Stream
,它绑定到socket
。然后,如果套接字关闭(通过代码或手动),则关闭流,如果您尝试对关闭的流执行任何操作,则会抛出异常。