【发布时间】:2021-11-13 19:05:25
【问题描述】:
所以我有一个服务器,它接受传入的连接,然后抓取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;
}
}
我在客户端上所做的只是
- 连接到服务器
- 创建一个 byte[] 并通过
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();,因为它是一个阻塞调用。
好像某处有超时,但我不知道是什么导致连接断开。
为什么我在服务器上收到异常?某处是否存在隐藏超时?
【问题讨论】:
-
我不是 C#-er,但我想 TcpClient 有办法设置 TCP 保持活动并调整其参数。
-
看起来TcpClient.Client 返回具有SetSocketOption 方法的底层套接字,您可以使用该方法配置TCP keep-alives.
-
TcpClient有SendTimeout和ReceiveTimeout可以设置。如果我没记错的话,默认超时是 1 分钟。 -
@Rafael 可能,我觉得这可能与 tcp 的工作方式以及假设如何存在 ACK 等有关,我在 TCP 方面还没有受过良好的教育,所以我可能是错的。
-
@WBuck 如果你能找到任何关于默认超时的文档,那就太棒了!