什么是TCP窗口更新? [英] What is a TCP window update?

查看:835
本文介绍了什么是TCP窗口更新?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为Java游戏制作我自己的自定义服务器软件(游戏和原始服务器软件是用Java编写的)。没有任何协议文档可用,所以我必须使用Wireshark读取数据包。

I'm making my own custom server software for a game in Java (the game and original server software were written with Java). There isn't any protocol documentation available, so I am having to read the packets with Wireshark.

当客户端连接服务器时,将其发送为Gzip格式的级别文件。在发送级别的大约94个数据包中,我的服务器使用ArrayIndexOutOfBoundsException崩溃客户端。根据原始服务器的捕获文件,它会在该点发送TCP窗口更新。什么是TCP窗口更新,以及如何使用SocketChannel发送一个?

While a client is connecting the server sends it the level file in Gzip format. At about 94 packets into sending the level, my server crashes the client with an ArrayIndexOutOfBoundsException. According to the capture file from the original server, it sends a TCP Window Update at about that point. What is a TCP Window Update, and how would I send one using a SocketChannel?

推荐答案

TCP窗口用于之间的流量控制连接上的对等体。对于每个ACK数据包,主机将发送窗口大小字段。该字段表示主机在满之前可以接收多少字节的数据。发件人不应发送超过该数据量。

TCP windows are used for flow control between the peers on a connection. With each ACK packet, a host will send a "window size" field. This field says how many bytes of data that host can receive before it's full. The sender is not supposed to send more than that amount of data.

如果客户端没有足够快地接收数据,窗口可能会变满。换句话说,当应用程序关闭除了从其套接字读取之外的其他操作时,TCP缓冲区可能会填满。当发生这种情况时,客户端将发送一个设置了窗口已满位的ACK数据包。此时,服务器应该停止发送数据。发送到具有完整窗口的计算机的任何数据包将被确认。 (这会导致行为不端的发送者重新发送。一个表现良好的发送者只会缓冲传出数据。如果发送端的缓冲区也填满,那么发送应用程序会在尝试向套接字写入更多数据时阻止!)

The window might get full if the client isn't receiving data fast enough. In other words, the TCP buffers can fill up while the application is off doing something other than reading from its socket. When that happens, the client would send an ACK packet with the "window full" bit set. At that point, the server is supposed to stop sending data. Any packets sent to a machine with a full window will not be acknowledged. (This will cause a badly behaved sender to retransmit. A well-behaved sender will just buffer the outgoing data. If the buffer on the sending side fills up too, then the sending app will block when it tries to write more data to the socket!)

这是一个TCP停顿。它可能由于很多原因而发生,但最终它只是意味着发送者的传输速度比接收者正在读取的速度快。

This is a TCP stall. It can happen for a lot of reasons, but ultimately it just means the sender is transmitting faster than the receiver is reading.

一旦接收端的应用程序重新开始从套接字读取,它将消耗一些缓冲数据,这释放了一些空间。接收器然后将发送窗口更新分组以告知发送器它可以传输多少数据。发送方开始发送其缓冲数据,流量应该正常流动。

Once the app on the receiving end gets back around to reading from the socket, it will drain some of the buffered data, which frees up some space. The receiver will then send a "window update" packet to tell the sender how much data it can transmit. The sender starts transmitting its buffered data and traffic should flow normally.

当然,如果接收方一直很慢,你可以反复停顿。

Of course, you can get repeated stalls if the receiver is consistently slow.

我已经说过,好像发送方和接收方不同,但实际上,两个对等方都在与每个ACK数据包交换窗口更新,并且任何一方都可以填满其窗口。

I've worded this as if the sender and receiver are different, but in reality, both peers are exchanging window updates with every ACK packet, and either side can have its window fill up.

总体消息是您不需要直接发送窗口更新数据包。欺骗一个人实际上是一个坏主意。

The overall message is that you don't need to send window update packets directly. It would actually be a bad idea to spoof one up.

关于你看到的例外......它不太可能是由窗口更新引起或阻止的包。但是,如果客户端读取速度不够快,则可能会丢失数据。在您的服务器中,您应该检查Socket.write()调用的返回值。它可能小于您尝试写入的字节数。如果发送方的发送缓冲区已满,则会发生这种情况,这可能发生在TCP停顿期间。您可能正在丢失字节。

Regarding the exception you're seeing... it's not likely to be either caused or prevented by the window update packet. However, if the client is not reading fast enough, you might be losing data. In your server, you should check the return value from your Socket.write() calls. It could be less than the number of bytes you're trying to write. This happens if the sender's transmit buffer gets full, which can happen during a TCP stall. You might be losing bytes.

例如,如果您尝试在每次写入调用时写入8192个字节,但其中一个调用返回5691,那么您需要在下一次呼叫时发送剩余的2501个字节。否则,客户端将看不到该8K块的剩余部分,并且您的文件在客户端比在服务器端更短。

For example, if you're trying to write 8192 bytes with each call to write, but one of the calls returns 5691, then you need to send the remaining 2501 bytes on the next call. Otherwise, the client won't see the remainder of that 8K block and your file will be shorter on the client side than on the server side.

这篇关于什么是TCP窗口更新?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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