TcpClient/NetworkStream 未检测到断开连接
TcpClient/NetworkStream not detecting disconnection
我使用 TcpClient
和 NetworkStream
为我们的游戏创建了一个简单的持久套接字连接。正常连接、发送消息和断开连接都没有问题(退出 app/server 关闭 down/etc)。
但是,我遇到了一些问题,在某些情况下,客户端没有检测到与服务器的断开连接。我测试这个的最简单方法是拔掉 wifi 盒上的网络电缆,或将 phone 设置为飞行模式,但它发生在游戏中间,否则应该是稳定的 wifi。
查看 NetworkStream
等的文档,它说检测断开连接的唯一方法是尝试写入套接字。很公平,除了,当我尝试时,写入通过,好像没有任何问题。我可以像这样写多条消息,一切似乎都很好。只有当我重新插入电缆时,它才会发现它已断开连接(所有消息都已缓冲?)。
TcpClient
设置为 NoDelay
,而且每次写入后都会调用 Flush()
。
我尝试过的:
- 正在写消息给
NetworkStream
- 不开心
CanWrite
、Connected
等所有 return true
TcpClient.Client.Poll( 1000, SelectMode.SelectWrite );
- return 正确
TcpClient.Client.Poll( 1000, SelectMode.SelectRead ) && TcpClient.Client.Available == 0
- return 正确
TcpClient.Client.Receive(buffer, SocketFlags.Peek) == 0
- 连接时,阻塞大约 10-20 秒,然后 return 为真。当没有服务器时,永远阻塞(?)
NetworkStream.Write()
- 不抛出错误
NetworkStream.BeginWrite()
- 不会抛出错误(甚至在调用 EndWrite()
时也不会)
- 设置
WriteTimeout
- 没有效果
- 有一个特定的时间我们没有收到来自服务器的消息(通常有一个保持活动状态)-我有这个,但删除了它,因为由于滞后我们得到了很多误报等等(有些客户会看到 10-20 秒的延迟)
那我是不是做错了什么?有什么方法可以让 NetworkStream
在写入应该断开连接的套接字时抛出错误(就像它应该的那样)?
我对keep-alive没问题(默认情况是服务器会通知客户端它有一段时间没有收到任何东西,客户端会发送一个心跳),但是在这一刻,根据 NetworkStream
一切都很好。
这是一个游戏,所以理想情况下检测应该足够快(因为用户仍然可以在游戏中移动,直到他们需要进行服务器调用,其中一些会阻止 UI,所以游戏似乎坏了)。
我使用的是 Unity,所以它是 .Net 2.0
is to pull out the network cable on the wifi box
这是一个很好的测试。如果您这样做,则不会通知远程方。它怎么可能发现?不能。
when I try, the write passes as if nothing is wrong
写入可以(并且正在)缓冲。他们最终进入了一个方块洞……没有回复。检测到这一点的唯一方法是超时。
So am I doing something wrong here?
您已经尝试了很多方法,但如果没有回复告诉您断开连接,您根本无法找出断开连接的原因。使用超时。
我使用 TcpClient
和 NetworkStream
为我们的游戏创建了一个简单的持久套接字连接。正常连接、发送消息和断开连接都没有问题(退出 app/server 关闭 down/etc)。
但是,我遇到了一些问题,在某些情况下,客户端没有检测到与服务器的断开连接。我测试这个的最简单方法是拔掉 wifi 盒上的网络电缆,或将 phone 设置为飞行模式,但它发生在游戏中间,否则应该是稳定的 wifi。
查看 NetworkStream
等的文档,它说检测断开连接的唯一方法是尝试写入套接字。很公平,除了,当我尝试时,写入通过,好像没有任何问题。我可以像这样写多条消息,一切似乎都很好。只有当我重新插入电缆时,它才会发现它已断开连接(所有消息都已缓冲?)。
TcpClient
设置为 NoDelay
,而且每次写入后都会调用 Flush()
。
我尝试过的:
- 正在写消息给
NetworkStream
- 不开心 CanWrite
、Connected
等所有 return trueTcpClient.Client.Poll( 1000, SelectMode.SelectWrite );
- return 正确TcpClient.Client.Poll( 1000, SelectMode.SelectRead ) && TcpClient.Client.Available == 0
- return 正确TcpClient.Client.Receive(buffer, SocketFlags.Peek) == 0
- 连接时,阻塞大约 10-20 秒,然后 return 为真。当没有服务器时,永远阻塞(?)NetworkStream.Write()
- 不抛出错误NetworkStream.BeginWrite()
- 不会抛出错误(甚至在调用EndWrite()
时也不会)- 设置
WriteTimeout
- 没有效果 - 有一个特定的时间我们没有收到来自服务器的消息(通常有一个保持活动状态)-我有这个,但删除了它,因为由于滞后我们得到了很多误报等等(有些客户会看到 10-20 秒的延迟)
那我是不是做错了什么?有什么方法可以让 NetworkStream
在写入应该断开连接的套接字时抛出错误(就像它应该的那样)?
我对keep-alive没问题(默认情况是服务器会通知客户端它有一段时间没有收到任何东西,客户端会发送一个心跳),但是在这一刻,根据 NetworkStream
一切都很好。
这是一个游戏,所以理想情况下检测应该足够快(因为用户仍然可以在游戏中移动,直到他们需要进行服务器调用,其中一些会阻止 UI,所以游戏似乎坏了)。
我使用的是 Unity,所以它是 .Net 2.0
is to pull out the network cable on the wifi box
这是一个很好的测试。如果您这样做,则不会通知远程方。它怎么可能发现?不能。
when I try, the write passes as if nothing is wrong
写入可以(并且正在)缓冲。他们最终进入了一个方块洞……没有回复。检测到这一点的唯一方法是超时。
So am I doing something wrong here?
您已经尝试了很多方法,但如果没有回复告诉您断开连接,您根本无法找出断开连接的原因。使用超时。