目前,我正在研究C#服务器/客户端项目,遇到一个奇怪的问题,虽然花了我一段时间才能解决,但对解决方案或更确切地说我为什么需要它并不完全满意。基本上,我发现向本地主机目标发送10kbyte以上的tcp套接字消息需要1ms的时间延迟。
作为背景,我在一台计算机上有一台服务器,许多客户机都连接到该服务器上,并来回传递信息,而这些信息似乎都可以正常工作。我也有连接到服务器本地的客户端。我面临的问题是,当邮件大小超过大约10 KB时,邮件将无法通过。我只是注意到了这一点,因为大多数发送的消息的大小约为1-2 KB,但是与服务器(本地主机)连接在同一台计算机上的客户端更多是管理客户端,因此发送/接收更多的数据。
真正的问题是服务器(发送方)正在从发送数据的C#发送命令返回true /成功,但是,接收方指示只有第一个块(如果我缓冲了)会通过,否则什么都没有。因此,我结束了连线工作,发现即使发送调用成功完成,实际上也不会通过连线发送任何数据(记住这是在本地环回接口上)。
我尝试玩弄如何发送数据并尝试所有不同的调用(NetworkStream.Write / NetworkStream.WriteAsync / Socket.Send / Socket.SendAsync / Socket.BeginSend
),以及缓冲数据或一次发送全部数据。直到我在循环中的两次发送调用之间设置了时间延迟,然后一切正常为止,一切似乎都没有改变(我测试了1.5GB的数据流,没有问题)。
我还发现延迟小于1ms / 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显示没有数据正在传输。我唯一的想法是库中的某些东西检测到它是本地目标,并使用从我那里提取的一些内部命名管道和缓冲区填充到某个地方?
我已经尝试搜索类似问题超过一个星期,但没有发现任何明显的问题,因此将不胜感激。
答案 0 :(得分:0)
根据以前的经验,我总是发现您是否需要“延迟”其他错误。
Righto。在这里,我怀疑您假设套接字上的“读取”将返回完整的消息。
但是TCP / IP是一种流协议,并且不包含任何消息概念。若要直接成功使用TCP / IP,必须定义“消息框架协议”,以与远程主机通信期望的字节数。我看不到您在留言前写任何东西,所以我怀疑那是缺少的内容。
许多人使用的简单解决方案是始终在消息的开头始终发送一个4字节的整数,该整数指示将要发送的字节数。然后,读取器可以执行4字节读取,然后执行读取循环,直到读取了预期的字节数。
答案 1 :(得分:0)
因此,该问题原来是计算机本身(或更确切地说是我们的许多开发箱)上的某些问题,这些问题影响了在本地主机绑定上托管/连接的任何服务。如果主机是本地主机,则包括许多网络服务,甚至包括IISExpress和IIS。这样一来,任何大小超过10 KB的数据都不会被发送/接收。
经过数天的努力弄清了哪些因素影响了localhost连接,我们最终重建了我们的开发箱,问题现在消失了(尽管我们仍然不知道为什么/是什么原因导致了问题)。