为什么当客户端不再发送任何数据时,我的连接会断开?



所以我有一个服务器,它接受传入的连接,然后抓住TcpClient,以便获得流,以便数据可以通过该流发送和接收。

就目前而言,我只是想读取数据,它工作得很好!唯一的问题是,如果我作为客户端向服务器发送数据,服务器就会像它应该的那样解释数据,它会按照预期的方式读取每一个比特。但是如果数据包在接下来的50 - 60秒内没有发送任何数据,服务器将抛出这个异常

无法从传输连接读取数据:远程主机强制关闭了现有连接.

一旦客户端连接,服务器就进入循环并开始读取数据,如下所示

while (isConnected)
{
var packetOpCode = nr.ReadByte();
var packetSize = Constants.INCOMING_SIZES[packetOpCode];
NetPacket packet;
/* i.e 127 */
packetSize = nr.ReadByte();
var payload = nr.ReadBytes(packetSize);
packet = new NetPacket
{
OpCode = packetOpCode,
Length = packetSize,
Payload = payload
};

_packets.Add(packet);
/* If anything here crashes, then treat it as a faulty packet and disconnect the user. */
Console.WriteLine(
$"#: {_id} Queue: [{_packets.Count}] - Packet with ID: {packet.OpCode} added. ");
File.AppendAllText("Log.txt",
$"#: {_id} Queue: [{_packets.Count}] - Packet with ID: {packet.OpCode} added. n");
}

其中nr是我的NetReader类的实例

public class NetReader : BinaryReader
{
private readonly NetworkStream _ns;
public NetReader(NetworkStream ns) : base(ns)
{
_ns = ns;
base.BaseStream.ReadTimeout = System.Threading.Timeout.Infinite;
}
}

我在客户端所做的就是

  • 连接服务器
  • 创建一个字节[]并通过Client.Send(..);
  • 发送它

所以它只发送一个数据包,然后它就空闲了,应用程序没有退出,它只是不再发送数据了

client.Connect("127.0.0.1", portNumber);
PacketBuilder builder = new PacketBuilder();
builder.AddOpCode(4);
builder.AddByte(4);
builder.AddString("Test");
var packet = builder.GetByteArray();
client.Client.Send(packet, packet.Length, SocketFlags.None);

数据包看起来像这样4 4 54 65 73 74

由于服务器正在循环,在读取第一个数据包后试图读取更多数据,因此第二次迭代将卡在var packetOpCode = nr.ReadByte();行上,因为它是阻塞调用。

这几乎是有一个超时的地方,但我不知道是什么使连接断开。

为什么我在服务器上得到异常?是否有一个隐藏的超时?

TCP不会超时,除非它的实现特别实现了超时。

一个已建立的TCP连接,如果100年不发送任何数据,仍然是一个已建立的TCP连接。

只要两端还存在,就没有理由向另一端发送数据包,它们可以永远坐在那里等待。

:

  1. 服务器和/或客户端可以关闭空闲连接以释放资源。

  2. 防火墙和NAT设备可以删除状态信息,这样当你再次使用它时,你的连接就不再工作了。

  3. 防火墙和NAT设备也可以通过向客户端或服务器发送RST来关闭空闲的tcp连接。

根据您的解释,听起来服务器正在关闭连接,因为它没有看到任何数据,因此它正在释放资源。

检查服务器实现

最新更新