windows - 如何避免http包合并?

标签 windows http go networking tcp

我编写 go 代码来发送 Http 流 block :

func handle02(w http.ResponseWriter, req *http.Request){
    for {
        n, err := w.Write([]byte("h\r\n"))
        if ww,ok := w.(http.Flusher); ok {
             ww.Flush()
        }
        time.Sleep(time.Millisecond * 10)
        if err != nil {
            fmt.Println(err, n)
            break
        }
    }
}

客户端接收 block 并打印它
import requests

a = requests.post(url, stream=True)
for line in a.iter_lines():
    if line:
        print(line)

它在win10和Linux上运行良好。但是当我在 Windows 服务器上运行客户端时,它会将这些 block 合并为一个数据包。我使用wireshark检查并发现它将 block 打包成一个大包。

enter image description here

但是在win10上,wireshark结果是
enter image description here

服务器的每次刷新都会在客户端产生一个小数据包。没关系。
我尝试了很多来自互联网的方法,比如
“禁用 tcp 自动调整”、“禁用 Nagle 算法”

但它们不起作用。
那么我怎么能禁止合并数据包呢?

谢谢

最佳答案

你在工作中使用了错误的方法。 HTTP 是 TCP 之上的协议(protocol),客户端发送请求,服务器发送响应。其中没有更精细的粒度,即无法控制何时发送和接收单个请求的响应的不同部分(HTTP 分 block 也不提供这种粒度)。

虽然在某些特定情况下可能偶然实现更细粒度的控制,但当涉及不同的操作系统、不同版本的库、代理等时,这种粒度很难维护——因为这些只关心需要的级别粒度 的标准,而不是您想要达到的标准滥用 HTTP 协议(protocol) .

如果你想有更精细的粒度,你必须 使用设计的协议(protocol)而不是因为它在某些特定情况下对您有用。这意味着您必须使用多个请求来获得多个响应,而不是本质上期望单个请求有多个响应。或者使用允许任意时间任意方向任意消息的 WebSockets。或者直接使用 TCP 也允许这样做。

编辑:根据评论,客户端在防火墙后面运行,服务器在外面。问题不太可能是由 Windows 与 Linux 引起的,但更有可能是由防火墙引起的。 防火墙可能使用(透明)代理 因此 OP 遇到了问题 described in the documentation for Flusher :

...if the client is connected through an HTTP proxy, the buffered data may not reach the client until the response completes



这也可以从数据包捕获中看出:在成功的情况下,可以看到 HTTP 分 block 的使用,即 33 0d 0a 68 0d 0a 0d 0a来自屏幕截图的是单个 HTTP block :
3\r\n     <<< this is the length of the chunk in hex
h\r\n     <<< this is the payload of the chunk
\r\n      <<< end of chunk

与此相反,在非工作情况下的数据包捕获中可以看到没有进行分 block ,即 68 0d 0a 68 0d 0a 68 0d 0a ...是:
h\r\n 
h\r\n
h\r\n
...

这意味着(透明)代理可能正在读取分 block 响应并将其作为未分 block 转发。这种行为并不少见,尤其是代理在防火墙中经常做的内容分析。但也可能是代理正在将客户端请求修改为 HTTP/1.0,在这种情况下,服务器首先不会使用 HTTP 分 block 编码,因为这仅支持 HTTP/1.1。

关于windows - 如何避免http包合并?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60688823/

相关文章:

c++ - 如何为 Windows 编写一个无法杀死的进程?

go - 如何将gif分割成图片

go - 用 Golang 替换文件中的一行

Java:如何异步发出http请求?

http - 使用 HTTP 和 HTTPS 发送/接收的数据差异

Angular 2 : convert array to Observable

go - 将带有 uint8_t *num 的 C 结构转换为 Go

python - 无法接收来自 Steam 和其他一些程序的击键

windows - TShark 输出重定向

c - Mac OS X 中的多线程