更快的方式使用TcpClient的沟通? [英] Faster way to communicate using TcpClient?

查看:109
本文介绍了更快的方式使用TcpClient的沟通?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写在C#中的客户机/服务器应用程序,它会很大。现在,一切正常,这一切都pretty的强劲。我的问题是,我遇到了一些延迟通过该连接发送数据包时。

I'm writing a client/server application in C#, and it's going great. For now, everything works and it's all pretty robust. My problem is that I run into some delays when sending packets across the connection.

在客户端上我做的:

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(),直到它有一个整体要求它的块,然后进行处理和使用写发送响应()。

(Left out some exception catching etc.) The server does the opposite, i.e. it blocks on NetworkStream.Read() until it has a whole request, then processes it and sends a response using Write().

写()的原始速度/阅读()不是一个问题(即发送大量的数据包快),但发送几个小数据包,一个接一个,而不关闭连接,可以非常慢(延迟50-100毫秒)。有什么奇怪的是,这些延迟出现,是典型的平次&LT局域网连接; 1毫秒,但如果服务器在本地主机上运行他们不发生,即使平时间会有效地将相同的(至少差应不是100毫秒的量级)上。这将是有意义的我,如果我重新打开了每个数据包的连接,导致大量的握手,但我不是。这就像如果服务器进入等待状态,扔了不同步的客户端,然后将其绊倒了一下,因为它重新建立什么本质上是一个失去的连接。

The raw speed of Write()/Read() isn't a problem (i.e. sending large packets is fast), but sending several small packets, one after another, without closing the connection, can be terribly slow (delays of 50-100 ms). What's strange is that these delays show up on LAN connections with typical ping times <1 ms, but they do not occur if the server is running on localhost, even though the ping time would effectively be the same (at least the difference should not be on the order of 100 ms). That would make sense to me if I were reopening the connection on every packet, causing lots of handshaking, but I'm not. It's just as if the server going into a wait state throws it out of sync with the client, and then it stumbles a bit as it reestablishes what is essentially a lost connection.

所以,我做错了?有没有一种方法,以保持同步,以便在服务器总是准备接收数据TCPSERVER和TcpClient的关系? (反之亦然:有时在处理请求的客户端需要几毫秒,然后客户端似乎并没有准备好接收来自服务器的响应,直到它有一些时间阻塞在阅读后醒来() 。)

So, am I doing it wrong? Is there a way to keep the connection between TcpServer and TcpClient synchronised so the server is always ready to receive data? (And vice versa: sometimes processing the request from the client takes a few ms, and then the client doesn't seem to be ready to receive the response from the server until it's had a few moments to wake up after blocking on Read().)

推荐答案

原来,我的服务器和客户端没有完全对称毕竟。我已经注意到,但我认为这并不重要的。显然,这是一个巨大的交易。具体而言,服务器这样做:

It turns out my server and client were not completely symmetrical after all. I had noticed, but I didn't think it mattered at all. Apparently it's a huge deal. Specifically, the server did this:

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

这点我变成这样的:

Which I changed into this:

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

而现在的延迟完全消失了,或至少它不再衡量单位为毫秒。所以,这有点像100X加速在那里。 \ O /

And now the delay is completely gone, or at least it's no longer measurable in milliseconds. So that's something like a 100x speedup right there. \o/

它仍然是奇数,因为它写完全相同的数据到插座和以前一样,所以我想在插座上的写操作,然后以某种方式传送给远端插口,这可能跨preT期间收到一些秘密元这是一个机会打个盹。如果不是这样,还是先写把插座进入接收模式,导致其绊倒时,它则要​​求重新发送之前,它已收到任何东西。

It's still odd because it's writing exactly the same data to the socket as before, so I guess the socket receives some secret metadata during the write operation, which is then somehow communicated to the remote socket, which may interpret it as an opportunity to take a nap. Either that, or the first write puts the socket into receive mode, causing it to trip up when it's then asked to send again before it has received anything.

我想的含义是,所有这一切例如code你发现躺在身边,它展示了如何写入和从固定大小的块(插座经常读取$由单个int描述pceded p $数据包的大小可依,同我的第一个版本),未能一提的是有一个非常沉重的性能损失这样做。

I suppose the implication would be that all of this example code you find lying around, which shows how to write to and read from sockets in fixed-size chunks (often preceded by a single int describing the size of the packet to follow, same as my first version), is failing to mention that there's a very heavy performance penalty for doing so.

这篇关于更快的方式使用TcpClient的沟通?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆