【发布时间】:2019-08-14 14:22:48
【问题描述】:
我目前正在开发一个 C# 服务器/客户端项目,遇到了一个奇怪的问题,我花了一段时间才解决,但对解决方案并不完全满意,或者更确切地说,我为什么需要它。基本上我发现向 localhost 目标发送超过 10kbytes 的 tcp 套接字消息需要 1ms 的时间延迟。
作为背景,我在一台机器上有一台服务器,许多客户端连接到该服务器并来回传递信息,这一切似乎都运行良好。我也有连接到服务器的本地客户端。我面临的问题是,当消息大小超过约 10kbytes 时,消息将无法通过。我只是注意到这一点,因为发送的大多数消息大小约为 1-2kbytes,但与服务器(本地主机)连接在同一台机器上的客户端更像是一个管理客户端,因此发送/接收更多数据。
真正的问题是服务器(发送方)从 C# 发送数据的命令返回 true / 成功,但是,接收方表示只有第一个块(如果我缓冲)会通过或根本没有.所以我最终打开了wireshark,发现即使发送调用成功完成,实际上也不会通过线路发送任何数据(记住这是在本地环回接口上)。
我尝试了如何发送数据并尝试所有不同的调用 (NetworkStream.Write / NetworkStream.WriteAsync / Socket.Send / Socket.SendAsync / Socket.BeginSend) 以及缓冲数据或一次性发送所有数据。直到我在循环中的发送调用之间设置一个时间延迟,然后一切都正常运行(我测试了高达 1.5GB 的数据流,没有任何问题),似乎没有任何区别。
我还发现任何低于 1 毫秒/10,000 个滴答声的延迟都会再次导致问题,我会通过这么多发送调用来工作,然后它们会再次停止。将TcpClient.NoDelay 设置为true 似乎也没有太大影响。
以下是我发送代码的一个示例,其中包含我尝试过的不同发送命令,它们都具有完全相同的行为。
// _client is an abstracted/based off a TcpClient object (the target)
byte[] dataBytes = Serializer.SerializeMessage(message);
int bytesSent = 0;
while (bytesSent < dataBytes.Length) {
int bytesToSend = ((dataBytes.Length - bytesSent) < 8192) ? (dataBytes.Length - bytesSent) : 8192;
//_client.Socket.Send(dataBytes, bytesSent, bytesToSend, SocketFlags.Partial);
//_client.NetworkStream.Write(dataBytes, bytesSent, bytesToSend);
//_client.Socket.BeginSend(dataBytes, bytesSent,bytesToSend,SocketFlags.None, ar => {int bytes = ((Socket)ar.AsyncState).EndSend(ar);}, _client.Socket);
_ = _client.NetworkStream.WriteAsync(dataBytes, bytesSent, bytesToSend);
bytesSent += bytesToSend;
Thread.Sleep(TimeSpan.FromTicks(10000));
}
因此,虽然现在这工作正常,但我的问题是为什么甚至需要它,根据以前的经验,我总是发现如果您需要“延迟”还有其他问题。此外,没有延迟,没有任何错误,所有调用都报告他们成功发送了字节,但wireshark显示没有数据正在传输。我唯一的想法是库中的某些东西检测到它是本地目标并使用从我那里抽象出来的一些内部命名管道并且缓冲区在某处填满?
我已经尝试搜索任何类似的问题一个多星期了,但找不到任何明显的东西,所以任何见解都将不胜感激。
【问题讨论】:
标签: c# sockets asynchronous networkstream