user-0 提问: tcp的发送窗口大小谁决定的？

回复:
user: user-1
content: 引用 24 楼 u012879787 的回复:[quote=引用 23 楼 DelphiGuy 的回复:] “接收端不断的回应win=0的报文给发送方”这应该是发送方使用持续定时器防止出现死锁（接收方窗口为0之后又恢复接收，但新的修改窗口大小的报文丢失，结果双方陷入互相等待的状态）的情况导致的，是接收方对发送方的探测数据的响应。可以参考tanenbaum的《computer networks》6.4.7 TCP定时器管理 部分。  他回复我邮件，他说的情况不是“死锁”！！！  而是： 假设发送端狂发100个包个接收方，接收方收到50个包后，就满了，于是win=0， 但是另外50个包已到路上了。  所以就就出现了连续回应win=0给发送端的情况。  他是著名公司EMC的网络工程师，包是他抓的。可信性是非常高！！！！！！   ———————————————————分割线—————————————————  TCP报文头部有一个窗口域，16位整数，所以最大65535，代表的含义是“在你接收到下一次应答之前最多还可以发送这么多字节的数据”（注意是“最多”，发送方也有自己拥塞控制），这个窗口值是动态变化的，接收端会根据缓冲情况在应答报文中修改这个窗口值，如果缓冲已满仍然接收到报文，报文会被丢弃，同时不应答，直到缓冲区有空闲为止。至于初始值，当然直接设置成65535或者当前空闲缓冲区的大小二者中的较小值。   怎么会不应答呢？　明显就会应答嘛。　   我刚才举得例子是EMC工程师在实战中遇到的问题。 [/quote]  假设发送端狂发100个包个接收方，接收方收到50个包后，就满了，于是win=0， 但是另外50个包已到路上了。 所以就就出现了连续回应win=0给发送端的情况.这种情况不可能发生，上面楼说的死锁是对的。你这个工程师朋友貌似不靠谱啊

user: user-2
content: 如果老是出现接收端发送win=0的响应报文，那就要看接收端的问题了，首先接收端的缓存是否足够大，这个会影响接收端的窗口，另外接收端的硬件设备是不是不能及时处理这些数据，还有就是接收端是否有其他非常耗cpu的其他程序，当然还得检查接收端本身的程序是否做了阻塞数据接收处理的操作了。

user: user-3
content: 重新生命->重新声明

user: user-3
content: 引用 24 楼 u012879787 的回复:[quote=引用 23 楼 DelphiGuy 的回复:] “接收端不断的回应win=0的报文给发送方”这应该是发送方使用持续定时器防止出现死锁（接收方窗口为0之后又恢复接收，但新的修改窗口大小的报文丢失，结果双方陷入互相等待的状态）的情况导致的，是接收方对发送方的探测数据的响应。可以参考tanenbaum的《computer networks》6.4.7 TCP定时器管理 部分。  他回复我邮件，他说的情况不是“死锁”！！！  而是： 假设发送端狂发100个包个接收方，接收方收到50个包后，就满了，于是win=0， 但是另外50个包已到路上了。  所以就就出现了连续回应win=0给发送端的情况。  他是著名公司EMC的网络工程师，包是他抓的。可信性是非常高！！！！！！   ———————————————————分割线—————————————————  TCP报文头部有一个窗口域，16位整数，所以最大65535，代表的含义是“在你接收到下一次应答之前最多还可以发送这么多字节的数据”（注意是“最多”，发送方也有自己拥塞控制），这个窗口值是动态变化的，接收端会根据缓冲情况在应答报文中修改这个窗口值，如果缓冲已满仍然接收到报文，报文会被丢弃，同时不应答，直到缓冲区有空闲为止。至于初始值，当然直接设置成65535或者当前空闲缓冲区的大小二者中的较小值。   怎么会不应答呢？　明显就会应答嘛。　   我刚才举得例子是EMC工程师在实战中遇到的问题。 [/quote]  TCP连接建立之后，发送窗口的大小是发送方的拥塞窗口和接收方承认的窗口大小之中较小的那个，所以不会出现所谓的“假设发送端狂发100个包个接收方，接收方收到50个包后，就满了，于是win=0， 但是另外50个包已到路上了”这种事情。 tanenbaum的书中 6.4.5 TCP传输策略 中明确说了： 当滑动窗口为0时，发送方一般不能再发送数据段，但有两种情况除外。一种情况是可以发送紧急数据，例如，允许拥护终止（kill）在远端机上的运行进程。另一种情况是发送方可以发送一个1字节的数据段通知接收放重新生命它希望接收的下一字节及窗口大小。TCP标准明确地提供了该选项以防止窗口声明丢失时出现死锁情况。 发送方不需要从应用程序一到来数据便发送出去。接收方也不需要尽早发送确认。

user: user-0
content: 引用 23 楼 DelphiGuy 的回复:“接收端不断的回应win=0的报文给发送方”这应该是发送方使用持续定时器防止出现死锁（接收方窗口为0之后又恢复接收，但新的修改窗口大小的报文丢失，结果双方陷入互相等待的状态）的情况导致的，是接收方对发送方的探测数据的响应。可以参考tanenbaum的《computer networks》6.4.7 TCP定时器管理 部分。  他回复我邮件，他说的情况不是“死锁”！！！  而是： 假设发送端狂发100个包个接收方，接收方收到50个包后，就满了，于是win=0， 但是另外50个包已到路上了。  所以就就出现了连续回应win=0给发送端的情况。  他是著名公司EMC的网络工程师，包是他抓的。可信性是非常高！！！！！！   ———————————————————分割线—————————————————  TCP报文头部有一个窗口域，16位整数，所以最大65535，代表的含义是“在你接收到下一次应答之前最多还可以发送这么多字节的数据”（注意是“最多”，发送方也有自己拥塞控制），这个窗口值是动态变化的，接收端会根据缓冲情况在应答报文中修改这个窗口值，如果缓冲已满仍然接收到报文，报文会被丢弃，同时不应答，直到缓冲区有空闲为止。至于初始值，当然直接设置成65535或者当前空闲缓冲区的大小二者中的较小值。   怎么会不应答呢？　明显就会应答嘛。　   我刚才举得例子是EMC工程师在实战中遇到的问题。

user: user-3
content: “接收端不断的回应win=0的报文给发送方”这应该是发送方使用持续定时器防止出现死锁（接收方窗口为0之后又恢复接收，但新的修改窗口大小的报文丢失，结果双方陷入互相等待的状态）的情况导致的，是接收方对发送方的探测数据的响应。可以参考tanenbaum的《computer networks》6.4.7 TCP定时器管理 部分。

user: user-0
content: up起来，等高手，

user: user-0
content: 引用 16 楼 DelphiGuy 的回复:TCP报文头部有一个窗口域，16位整数，所以最大65535，代表的含义是“在你接收到下一次应答之前最多还可以发送这么多字节的数据”（注意是“最多”，发送方也有自己拥塞控制），这个窗口值是动态变化的，接收端会根据缓冲情况在应答报文中修改这个窗口值，如果缓冲已满仍然接收到报文，报文会被丢弃，同时不应答，直到缓冲区有空闲为止。至于初始值，当然直接设置成65535或者当前空闲缓冲区的大小二者中的较小值。   TCP报文头部有一个窗口域，16位整数，所以最大65535，代表的含义是“在你接收到下一次应答之前最多还可以发送这么多字节的数据”（注意是“最多”，发送方也有自己拥塞控制），这个窗口值是动态变化的，接收端会根据缓冲情况在应答报文中修改这个窗口值，如果缓冲已满仍然接收到报文，报文会被丢弃，同时不应答，直到缓冲区有空闲为止。至于初始值，当然直接设置成65535或者当前空闲缓冲区的大小二者中的较小值。   建议修改答案，看我用颜色标示的话。   我见过一个网络工程师分析报文，接收端不断的回应win=0的报文给发送方，  至于为什么不断的回应win=0.，肯定是接收方不断发送数据所致，连续收到win=0的报文，  发送方不会立即停止发送，很可能还会继续发送几次，最终停止发送。  我在联系“那个网络工程师”，希望从他那得到报文为什么是那样的原因，如果有消息，我会继续回复此贴。

user: user-3
content: 引用 19 楼 u012879787 的回复:[quote=引用 16 楼 DelphiGuy 的回复:] TCP报文头部有一个窗口域，16位整数，所以最大65535，代表的含义是“在你接收到下一次应答之前最多还可以发送这么多字节的数据”（注意是“最多”，发送方也有自己拥塞控制），这个窗口值是动态变化的，接收端会根据缓冲情况在应答报文中修改这个窗口值，如果缓冲已满仍然接收到报文，报文会被丢弃，同时不应答，直到缓冲区有空闲为止。至于初始值，当然直接设置成65535或者当前空闲缓冲区的大小二者中的较小值。 注意是“最多”，发送方也有自己拥塞控制   １.　是说“拥塞窗口”这个概念，只是发送方控制这个意思吗？  ２.　　拥塞控制————只是由发送方决定吗？ 还是发送方、接受方两者来决定？  ３.　另外发送方的拥塞控制是指什么？   ３个问题，谢谢。      [/quote]  你不是已经知道了么。  引用 楼主 u012879787 的回复:发送窗口的大小因素有2部分： 拥塞、和接收方的接受窗口。  假设网络很好，没有出现拥塞。 那么发送方的发送窗口大小就由接收方的接受窗口大小决定。  可以参考tanenbaum的《计算机网络》一书6.4.6 TCP拥塞控制 那部分。

user: user-2
content: 引用 14 楼 scy2510 的回复:翻书看了理论的说法，不知道与实际相差有多大  也正好在看TCP协议详解1，当中20.4提到，接受方提供的窗口大小可以由接收进程控制，这将影响TCP性能。 从接下来文字中可看出接受方提供的窗口大小其实就是接收端缓存大小。 这个大小可以是默认，也可以用API配置  比如WIN SOCKET，setsockopt 对单独SOCKET设置 从20.7.1中可看出，窗口大小的设置应该考虑通道的时延带宽乘积（作为协议去优化或者人为优化的依据）。  请有实战经验的来说说 比如协议出处 接收的缓存要比窗口大小大得多，一般的窗口大小是MSS的几倍，10几倍。

user: user-4
content: 翻书看了理论的说法，不知道与实际相差有多大  也正好在看TCP协议详解1，当中20.4提到，接受方提供的窗口大小可以由接收进程控制，这将影响TCP性能。 从接下来文字中可看出接受方提供的窗口大小其实就是接收端缓存大小。 这个大小可以是默认，也可以用API配置  比如WIN SOCKET，setsockopt 对单独SOCKET设置 从20.7.1中可看出，窗口大小的设置应该考虑通道的时延带宽乘积（作为协议去优化或者人为优化的依据）。  请有实战经验的来说说 比如协议出处

user: user-5
content: 这是协议规定的，你去研究研究RFC文档。 我记得是有上限，通过数次的交互最终确定一个比较可靠的窗口大小。

user: user-2
content: 引用 11 楼 bsnry 的回复:没看清，劳累再解释一下，这个概念我很模糊你说的发送窗口大小的相关因素都没错，只是楼主想知道接收端的窗口大小是怎么一回事

user: user-0
content: 引用 14 楼 scy2510 的回复:翻书看了理论的说法，不知道与实际相差有多大  也正好在看TCP协议详解1，当中20.4提到，接受方提供的窗口大小可以由接收进程控制，这将影响TCP性能。 从接下来文字中可看出接受方提供的窗口大小其实就是接收端缓存大小。 这个大小可以是默认，也可以用API配置  比如WIN SOCKET，setsockopt 对单独SOCKET设置 从20.7.1中可看出，窗口大小的设置应该考虑通道的时延带宽乘积（作为协议去优化或者人为优化的依据）。  请有实战经验的来说说 比如协议出处 ，当中20.4提到，接受方提供的窗口大小可以由接收进程控制，这将影响TCP性能。   接受进程控制？内核不控制？我已经说过，即使应用层不从内核缓存中拷贝走数据，内核也会回应ack给发送方。 可见接受窗口的大小，不应该是完全是由接受进程控制！  接受进程如果拷贝走数据，接受窗口会增大，这也说明，接受窗口大小有可能是由接受进程控制！     从接下来文字中可看出接受方提供的窗口大小其实就是接收端缓存大小。  你这里的缓存是指什么缓存？

user: user-0
content: 引用 16 楼 DelphiGuy 的回复:TCP报文头部有一个窗口域，16位整数，所以最大65535，代表的含义是“在你接收到下一次应答之前最多还可以发送这么多字节的数据”（注意是“最多”，发送方也有自己拥塞控制），这个窗口值是动态变化的，接收端会根据缓冲情况在应答报文中修改这个窗口值，如果缓冲已满仍然接收到报文，报文会被丢弃，同时不应答，直到缓冲区有空闲为止。至于初始值，当然直接设置成65535或者当前空闲缓冲区的大小二者中的较小值。 注意是“最多”，发送方也有自己拥塞控制   １.　是说“拥塞窗口”这个概念，只是发送方控制这个意思吗？  ２.　　拥塞控制————只是由发送方决定吗？ 还是发送方、接受方两者来决定？  ３.　另外发送方的拥塞控制是指什么？   ３个问题，谢谢。

user: user-6
content: 不是setsockopt设置的吗？  setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &window_size, sizeof(window_size));

user: user-3
content: TCP报文头部有一个窗口域，16位整数，所以最大65535，代表的含义是“在你接收到下一次应答之前最多还可以发送这么多字节的数据”（注意是“最多”，发送方也有自己拥塞控制），这个窗口值是动态变化的，接收端会根据缓冲情况在应答报文中修改这个窗口值，如果缓冲已满仍然接收到报文，报文会被丢弃，同时不应答，直到缓冲区有空闲为止。至于初始值，当然直接设置成65535或者当前空闲缓冲区的大小二者中的较小值。

user: user-0
content: 引用 2 楼 pengzhixi 的回复:发送窗口大小看已发送出去的数据包是否收到响应来决定，比如 你发了5个数据包出去，只收到头两个数据包得响应那么剩余的三个已经发送出去的数据包还必须留在发送窗口里面，也就是说这3个数据包在窗口里面要占空间，这个时候发送窗口大小自然变小了。  可是我问的是，接受窗口大小如何计算？  前提————没有拥塞的情况下，发送窗口由接受窗口大小决定，  接受窗口如何计算？  内核不管应用层有没有从内核缓存里拷贝走数据，就会回应应答报文。既然回应了，那么内核根据什么计算接受窗口大小。

user: user-2
content: 发送窗口大小看已发送出去的数据包是否收到响应来决定，比如 你发了5个数据包出去，只收到头两个数据包得响应那么剩余的三个已经发送出去的数据包还必须留在发送窗口里面，也就是说这3个数据包在窗口里面要占空间，这个时候发送窗口大小自然变小了。

user: user-0