V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
g0t3n
V2EX  ›  问与答

关于tcp如何维持通信 (不是keepalive的问题)

  •  
  •   g0t3n · 2013-11-10 18:38:48 +08:00 · 4863 次点击
    这是一个创建于 4024 天前的主题,其中的信息可能已经有所发展或是发生改变。
    网上貌似很多讲解 tcp 三握手和四挥手方面的知识,可是我有个问题就是,tcp如何维持连接呢?就是说三握手后,双方除了send/recv发送实际含数据的包外,会不会在发送握手包例如 ack包什么的来维持连接呢? 有什么书籍能讲解下这方面知识滴求大婶们指点指点哇
    14 条回复    1970-01-01 08:00:00 +08:00
    rrfeng
        1
    rrfeng  
       2013-11-10 18:43:23 +08:00
    维持?

    如果互不发送数据,那么空闲超时计时器就起作用了,会认为链接已经断开。

    本身好象是不会发送维持状态的包的,应用里自己写一个,10s hello 一次之类的……
    wy315700
        2
    wy315700  
       2013-11-10 19:06:13 +08:00
    发的心跳包吧
    damngood
        3
    damngood  
       2013-11-10 19:48:15 +08:00
    应该是不会的, 不过最好还是在应用级别实现 心跳/ping 之类的机制来确认连接性

    记得是说像 NAT 之类的设备会主动关闭有一段时间没有活跃了的连接..
    akira
        4
    akira  
       2013-11-10 20:04:13 +08:00
    主动发下心跳包就好了。
    go
        5
    go  
       2013-11-10 20:11:19 +08:00
    一般就是心跳机制
    lehui99
        6
    lehui99  
       2013-11-10 20:51:05 +08:00
    tcp本身的默认设置是没有心跳包的,不发数据则不会有任何数据包发送出去。所以一些tcp/ip协议的书(比如《TCP/IP协议详解》)中通常会有一个比较经典的例子:
    一个tcp连接建立之后没有任何数据发送,两个终端之间的路由器(当然不能是终端直连的那个)断电了无数次,甚至有长达几天的断电,终端还无感知,几个月后这个tcp连接仍旧建立着。
    之后一个终端突然断电了,另一个终端仍旧无感知,查看tcp状态还是established。
    tcp的解决方法是设置keepalive,隔一段时间会发心跳包。当然这是可选的,默认是不打开的设置。
    HunterPan
        7
    HunterPan  
       2013-11-10 23:09:09 +08:00
    @lehui99 你的意思是Tcp有自己的机制来维持心跳了?怎么日常情况下都是需要自写心跳包,小弟对Tcp研究不深
    yfdyh000
        8
    yfdyh000  
       2013-11-10 23:30:50 +08:00
    @HunterPan SO_KEEPALIVE,默认两小时。
    lehui99
        9
    lehui99  
       2013-11-11 10:03:37 +08:00 via Android
    楼上说的就是我说的keepalive选项
    g0t3n
        10
    g0t3n  
    OP
       2013-11-11 10:54:43 +08:00
    @yfdyh000 设置 keepalive 会引起全局tcp连接都发送心跳包。所以如ssh什么得都会自己实现心跳包。不过其实我的问题应该是: 除了keepalive外,tcp建立连接后还会发送其他什么包来维持/传输数据吗?
    tywtyw2002
        11
    tywtyw2002  
       2013-11-11 11:45:09 +08:00
    @g0t3n tcp不去检查连接状态。

    看看rfc吧,实在不行看 tcpip详解。。。。

    生存检查都是上层协议干的(程序)

    你说的这个tcp连接维持有些类似,udp的丢包检测。udp本身不去做丢包检测,是上层协议去管的丢包检测。
    tcp也一样,tcp自己不去管,但是上层去管。



    @lehui99 的例子不错,只要2个主机不挂,中间的网络挂了n次,那么tcp连接也不会中断。

    以ssh为例,如果电脑从休眠恢复过来,ssh client的tcp连接还是established,如果这时候按回车,程序会按照原来的tcpip序列号去和服务器端进行交涉。注意这时的sport和src都是不变的,如果有公网ip,并且没有设置keepalive,这个连接还会继续的。
    但是现在的网络环境都是nat。nat默认30分钟没有活动自动删除端口。所以这是如如果用的是内网ip,那么肯定无法连接了,因为sport改了,再去连服务器,回来的肯定是rst了。收到rst后,ssh客户端就会认为连接关闭了。。。

    其次还有如果ip变换了,主机上类似的操作就是把网卡down掉,在up一下,这个操作会吧tcpip协议栈清空。
    lehui99
        12
    lehui99  
       2013-11-11 15:28:05 +08:00 via Android
    @tywtyw2002 说的不错,如果终端之间不存在nat,那么几个月后双方仍旧可以正常通讯。可以说是nat破坏了tcpip的rfc规范,不过这也是没办法才这样的
    tywtyw2002
        13
    tywtyw2002  
       2013-11-12 13:31:00 +08:00
    @lehui99 其实nat特没破坏,破换是因为多内网ip对一个公网ip。

    我在学校有台服务器是内网地址,然后网关处nat倒唯一一个ipv4地址,这种情况也没有断掉。
    断掉还是因为 nat设备清了nathash表
    lehui99
        14
    lehui99  
       2013-11-12 21:22:39 +08:00
    @tywtyw2002 嗯,我指的是一种nat(snat),不是说所有的nat都是
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   977 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 22:53 · PVG 06:53 · LAX 14:53 · JFK 17:53
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.