本文介绍了插座“冲洗"通过暂时启用 NoDelay的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 C# 中有一个 HTTP 服务器的实现.使用 ab 我发现了一个奇怪的性能问题.每个请求在关闭 Keep-Alive 时需要 5 毫秒,但在开启 Keep-Alive 时需要 40 毫秒!

I have an implementation of an HTTP server in C#.Using ab I discovered a weird performance issue.Each request took 5 ms with Keep-Alive Off but 40 ms with Keep-Alive on!

测试页被生成为单个字节[],使用单个 socket.Send 调用作为回复发送.

The testpage is generated into a single byte[] which get sent as reply using a single socket.Send call.

据我所知,原因是 TCP 堆栈中使用的 Nagle 算法.

The cause is as far as I can tell Nagle's algorithm used in the TCP stack.

到目前为止,我使用的是 NoDelay 属性在每个服务的 HTTP 请求的末尾.

So far I am using the NoDelay property in the end of every HTTP request served.

socket.NoDelay = true;
socket.NoDelay = false;

现在确实解决了问题.但我没有任何文件来支持我的发现.

Which does solve the problem for now. But I have no documentation to backup my discovery.

这是在 linux/mono 系统上测试的.

This was tested on a linux/mono system.

是否有刷新 TCP 连接的标准方法?

这个答案 正在解决同样的问题.这里的不同之处在于我只想暂时禁用算法.

This answer is addressing the same issue. The difference here is that I am looking to only temporarily disabling the algorithm.

推荐答案

我用 Wireshark 对此进行了测试.不幸的是,

I tested this with Wireshark. Unfortunately,

socket.NoDelay = true;
socket.NoDelay = false;

没有效果.同样,

socket.NoDelay = true;
socket.Send(new byte[0]);
socket.NoDelay = false;

也没有效果.从观察到的行为来看,NoDelay 属性似乎只影响下一次使用非空缓冲区调用 Send.换句话说,您必须在 NoDelay 生效之前发送一些实际数据.

also has no effect. From observed behaviour, it appears that the NoDelay property only affects the next call to Send with a non-empty buffer. In other words, you have to send some actual data before NoDelay will have any effect.

因此,我得出的结论是,如果您不想发送任何额外的数据,则无法显式刷新套接字.

Therefore, I conclude that there is no way to explicitly flush the socket if you don’t want to send any extra data.

但是,由于您正在编写 HTTP 服务器,因此您可以使用一些技巧:

However, since you are writing an HTTP server, you may be able to use a few tricks:

  • 对于使用 Transfer-Encoding: chunked 服务的请求,您可以发送流结束标记("0") 和 NoDelay = true.
  • 如果您从本地文件系统提供文件,您将知道文件何时结束,因此您可以在发送最后一个块之前设置 NoDelay = true.
  • 对于使用 Content-Encoding: gzip 服务的请求,您可以在关闭 gzip 流之前设置 NoDelay = true;gzip 流将在实际完成和关闭之前发送一些最后的位.
  • For requests that are served using Transfer-Encoding: chunked, you can send the end-of-stream marker (the "0") with NoDelay = true.
  • If you are serving a file from the local filesystem, you will know when the file ends, so you could set NoDelay = true just before sending the last chunk.
  • For requests that are served using Content-Encoding: gzip, you can set NoDelay = true just before closing the gzip stream; the gzip stream will send some last bits before actually finishing and closing.

我现在肯定要把上面的内容添加到我的 HTTP 服务器:)

I’m certainly going to add the above to my HTTP server now :)

这篇关于插座“冲洗"通过暂时启用 NoDelay的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-20 23:44