seufy88 发表于 2014-04-02 16:07

gaojl0728 发表于 2014-04-02 14:08 static/image/common/back.gif
回复 7# timespace



应该是:

“close后,l_onoff非0且l_linger=0, 只有在此时TCP的读队列有数据的情况下, 才会暴力发送RST, 否则内核还是会四次握手的。”

gaojl0728 发表于 2014-04-02 16:12

回复 10# timespace


不好意思是我回复有点问题, 说的不太全面:
调用close后, 内核会先检查TCP读取队列,
1. 如果有数据没有读完, 不管linger选项是任何值, 内核总是会发送RST给对端,
2. 如果没有数据可读,内核接着检查linger选项, 如果l_onoff非0且l_linger=0, 也会发送RST
3. 其他情况会发送FIN进行四次挥手。同时如果l_onoff非0且l_linger>0,close调用会阻塞在这里等待l_linger的时间。

所以你说的情况也会发送RST的。

gaojl0728 发表于 2014-04-02 16:19

回复 11# seufy88


      那我回复写的有问题,他说的是对的。close完整的流程看我楼上的回复。

seufy88 发表于 2014-04-02 16:25

回复 9# gaojl0728


    请问,如果socket的引用数>2, 此时close(socket),在减少引用数的基础上,应该不会发送FIN吧,因为其他共享这个socket 的进程需要使用


(2)如果此后收到的是带ACK的纯数据包,会有所不同,
      a. 如果前面是close调用, local端进入FIN_WAIT2, 同时启动time wait定期器,最终会关闭local端的TCP链接.
==》进入FIN_WAIT2后,就不接收对方发来的data 了吗?
我的理解是,local侧还是可以继续接收数据并返回ack, 只是这些数据丢弃掉了。application对这个socket当然肯定也不能再read

seufy88 发表于 2014-04-02 16:41

@timespace
@gaojl0728
感谢两位的解答。

gaojl0728 发表于 2014-04-02 16:56

回复 14# seufy88


我前面说“同时启动time wait定期器,最终会关闭local端的TCP链接”是基于一般情况下local调用close发送了FIN给对端之后, 对端这时应该会发送FIN+ACK包回来的情况,但如果对端来的还不是FIN+ACK包,而是数据包,
1. 如果数据包带ACK,这些数据包还是会进入TCP收队列,
2. 如果数据包不带ACK, 直接丢掉。

不过Linux这块代码好像有点问题, 如果对端发来的是纯FIN包, 而不是FIN+ACK包,内核也会丢掉。
也就是说对端回过来FIN+ACK, 没问题。但是先回FIN, 再回ACK就不行了, 很奇怪。不太符合协议。

gaojl0728 发表于 2014-04-02 17:09

回复 16# gaojl0728


完整的过程是本端调用close发送FIN给对方, 此时本端进入FIN_WAIT_1,
如果此时对端发过来不带ACK的包(包括纯FIN包和纯数据包),直接丢掉, 如果是带ACK的数据包, 本端会进入FIN_WAIT_2, 同时这个数据包也会进入TCP队列, 此后如果来的还是带ACK的数据包, 数据包还能进入TCP队列。
直到FIN+ACK为止, 其他包都丢掉了。

gaojl0728 发表于 2014-04-02 17:09

回复 16# gaojl0728


完整的过程是本端调用close发送FIN给对方, 此时本端进入FIN_WAIT_1,
如果此时对端发过来不带ACK的包(包括纯FIN包和纯数据包),直接丢掉, 如果是带ACK的数据包, 本端会进入FIN_WAIT_2, 同时这个数据包也会进入TCP队列, 此后如果来的还是带ACK的数据包, 数据包还能进入TCP队列。
直到FIN+ACK为止, 其他包都丢掉了。

seufy88 发表于 2014-04-02 17:16

回复 12# gaojl0728


    如此说来,对于以close方式主动关闭的一侧,是有很大程度会造成RST,而不是正常的四次BYBY
timing很重要。直接close的时候,并不能保证buffer队列里没有要读的数据。

seufy88 发表于 2014-04-02 17:20

gaojl0728 发表于 2014-04-02 17:09 static/image/common/back.gif
回复 16# gaojl0728




完整的过程是本端调用close发送FIN给对方, 此时本端进入FIN_WAIT_1,

=》 本端发送完FIN后,如果之前本端发送的数据segment有丢失,对方会一直请求这个丢失的segment的序列号,些时,本端还是可以重发的吧?
直到对方对这个segment进行ACK(也可能对方重新收到丢失的segment后,直接发送FIN的ACK)

页: 1 [2] 3 4
查看完整版本: socket中close和shutdown的区别