首页 文章

使用TcpClient进行通信的速度更快?

提问于
浏览
8

我正在用C#编写客户端/服务器应用程序,而且它很棒 . 现在,一切正常,而且非常强大 . 我的问题是,当通过连接发送数据包时,我遇到了一些延迟 .

在客户端我这样做:

NetworkStream ns = tcpClient.GetStream();

// Send packet

byte[] sizePacket = BitConverter.GetBytes(request.Length);
byte[] requestWithHeader = new byte[sizePacket.Length + request.Length];
sizePacket.CopyTo(requestWithHeader, 0);
request.CopyTo(requestWithHeader, sizePacket.Length);

ns.Write(requestWithHeader, 0, requestWithHeader.Length);

// Receive response

ns.Read(sizePacket, 0, sizePacket.Length);
int responseLength = BitConverter.ToInt32(sizePacket, 0);
byte[] response = new byte[responseLength];

int bytesReceived = 0;
while (bytesReceived < responseLength)
{
  int bytesRead = ns.Read(response, bytesReceived, responseLength - bytesReceived);
  bytesReceived += bytesRead;
}

(遗漏了一些异常捕获等)服务器执行相反的操作,即它在NetworkStream.Read()上阻塞,直到它有一个完整的请求,然后处理它并使用Write()发送响应 .

Write()/ Read()的原始速度不是问题(即发送大数据包很快),但是在不关闭连接的情况下一个接一个地发送几个小数据包可能非常慢(延迟50-100)女士) . 奇怪的是,这些延迟出现在LAN连接上,典型的ping时间<1 ms,但如果服务器在localhost上运行则不会发生,即使ping时间实际上是相同的(至少差异不应该是大约100毫秒) . 如果我在每个数据包上重新打开连接,导致大量握手,那对我来说是有意义的,但我不是 . 这就好像服务器进入等待状态会使它与客户端失去同步,然后在重新 Build 本质上是丢失的连接时发现它有点绊倒 .

那么,我做错了吗?有没有办法保持TcpServer和TcpClient之间的连接同步,以便服务器随时准备接收数据? (反之亦然:有时处理来自客户端的请求需要几毫秒,然后客户端似乎没有准备好接收来自服务器的响应,直到它在Read()上阻塞之后有一些时刻被唤醒 . )

1 回答

  • 7

    事实证明,我的服务器和客户端毕竟不是对称的 . 我注意到了,但我并没有做出什么大不了的事 . 具体来说,服务器这样做:

    ns.Write(sizePacket, 0, sizePacket.Length);
    ns.Write(response, 0, response.Length);
    

    我改成了这个:

    // ... concatenate sizePacket and response into one array, same as client code above
    ns.Write(responseWithHeader, 0, responseWithHeader.Length);
    

    而现在延迟完全消失了,或者至少它在几毫秒内不再可测量 . 所以这就像100倍的加速一样 . \ O /

    它仍然很奇怪,因为它正在向套接字写入与以前完全相同的数据,所以我想套接字在写操作期间会收到一些秘密元数据,然后以某种方式传递给远程套接字,这可能会将其解释为机会小憩 . 要么就是这样,要么第一次写入使套接字进入接收模式,导致它在接收任何东西之前被要求再次发送时绊倒 .

    我想这意味着所有这些示例代码都会出现,它显示了如何以固定大小的块来写入和读取套接字(通常在前面跟一个描述要跟随的数据包大小的int,如同我的第一个版本)没有提到这样做的性能损失非常严重 .

相关问题