V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
amiwrong123
V2EX  ›  程序员

TCP 握手中,怎么理解从 LISTEN 转换到 SYN_SENT?

  •  
  •   amiwrong123 · 2021-12-18 22:08:51 +08:00 · 1935 次点击
    这是一个创建于 1074 天前的主题,其中的信息可能已经有所发展或是发生改变。

    正常情况下,是上图这样的。就不会有 LISTEN 转换到 SYN_SENT 。

    但是好像也存在从 LISTEN 转换到 SYN_SENT 的。 我简单画了个图,不知道下面这样对不对。( https://www.zhihu.com/question/50200176

    但我看到书中有这么一句话,就是说,只有 LISTEN 状态下的套接字才可以接受到 SYN 报文段。

    那我就有个疑问了,我理解 客户端那边是不会有 LISTEN 状态的套接字的,那么客户端怎么能接受到 服务器发来的 SYN 报文呢

    5 条回复    2021-12-19 13:58:21 +08:00
    choury
        1
    choury  
       2021-12-18 23:59:01 +08:00 via Android
    给你个关键字 tcp 打洞
    TomChaai
        2
    TomChaai  
       2021-12-19 00:40:24 +08:00
    因为两边可以理解为不是同一条 TCP 连接,客户端先建立一个 TCP 要求服务器开始个业务,服务器反而转变为客户端,尝试把原来的客户端当作服务器尝试建立另一个连接。
    这是应用层的设计导致传输层状态变化的例子,不能简单从传输层理解。
    3dwelcome
        3
    3dwelcome  
       2021-12-19 01:12:35 +08:00
    那个知乎的 FTP 回答有问题,我去 GITHUB 查了代码,有看到:

    Serv-U FTP Server v6.3
    on PORT command, the client listen on a port and wait the server to connect.
    on PASV command, the server listen on a port and wait the client to connect.

    说明在 FTP 里,服务器去反向连接客户端,并不是 listen socket 的内置状态切换,而是就是普通的客户端 listen 监听,服务端 connect 连接罢了。

    可能早期 TCP/IP 协议里有设计 LISTEN 转换到 SYN_SENT ,随着时间推移,已经被淘汰了。

    我甚至都不知道转换代码要怎么写,也没从看到过案例。
    sisylocke
        4
    sisylocke  
       2021-12-19 01:29:10 +08:00
    我不同意这是应用层的设计导致的问题,这些差别就是 TCP 协议的不同实现。

    首先你的图客户端和服务端是不是弄反了,一般把被动打开的一方称为服务端,主动的一方称为客户端。

    在建立 TCP 连接的时候,客户端和服务端各自都需要初始化一个控制块( TCB ),根据 RFC793 的建议的标准做法,这个连接的初始状态就是 Listen 。但是在具体实现的时候就会发现这一步是多余的。客户端在初始化 TCB 后发送 SYN ,然后状态立即变为 SYNSENT ;服务端接收 SYN 请求,然后初始化一个 TCB 后,状态又立即变为 SYN-RCVD 。所以 Listen 状态是一个很短暂的状态,完全可以一步到位将 TCB 初始化为 SYN 或者 SYNRCVD 状态。

    所以在新连接的时候一般不会出现 LISTEN 状态,但是不是说 LISTEN 状态就没用了。当接受到 RST 的时候,并不一定代表对方是关闭连接,所以有的 TCP 实现并不会直接丢弃这个连接,而是重新初始化 TCB 等待重新握手恢复连接,这时的状态就是 LISTEN 。
    Caturra
        5
    Caturra  
       2021-12-19 13:58:21 +08:00
    https://www.rfc-editor.org/rfc/pdfrfc/rfc793.txt.pdf

    状态转移可以看 PDF 第 29 页(原文 Page23 )

    我觉得不应该看它是客户端还是服务端,而是他现在处于什么状态,能处理什么行为
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5275 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 119ms · UTC 09:36 · PVG 17:36 · LAX 01:36 · JFK 04:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.