tcp如何维护长连接

上次提到tcp数据流无边界特点

还有一个特点那就是

TCP有长连接和短连接之分

目录结构:

tcp连接的终止

01

socke正常关闭

流程:

  • 被动关闭一方接受完毕数据 然后发送 TCP flag Fin请求
  • 主动关闭一方 tcp状态 进入TIME-WAIT
  • 主动关闭一方 在此期间内 该端口不能被任何程序重用 ,不能建立任何连接。这个期间称为平静时间(quiet time)

分析处于 T I M E _ WA I T状态的主机收到使其进入此状态的重复的 F I N时 所发生的情况。--重新计时

Q1 问题来了 TIME-WAIT 影响了端口马上被重用存在意义?

根据tcp状态含义解释 TIME-WAIT:等待足够的时 (等待),确保远程TCP收到了终止请求的确认 远程TCP收ack确认(这个条件) 直接 CLOSE-WAIT状态进入CLOSED状态 目的保证最后一步ack安全到达

但是我还是不明白存在意义 有更加合理解释吗?

02

sokcet 异常关闭

分析处于T I M E _ WA I T状态的主机收到一个 R S T时所发生的情况。

--断开连接

Q2 问题来了 如何减少TIME_WAIT时间

通过修改socket选项SO_LINGER 异常关闭连接 打破四次握手, 避免j进入TIME_WAIT状态

03

异常情况

  1. 客户端崩溃 异常关闭 server收不到ACK
  2. 客户端曾经崩溃,但已经重启 响应是一个复位reset
  3. 客户端主机活跃运行,但从服务器不可到达 T C P连接的双方都没有向对方发送数据
  4. 服务器主机突然断电 T C P连接的双方都没有向对方发送数据
  5. 服务器主机网线被拔出 T C P连接的双方都没有向对方发送数据
  6. 服务器主机正常重启当 系统被操作员关闭时,所有的应用程序进程(也就是客户端进程)都将被终止,客户端TCP会在连接上发送一个FIN。

心跳检查几种方案

04

TCP KeepAlive通过定时发送探测

缺点:

1 有时候检查不到 断电、直接拔掉网线、防火墙这些断线 (呜呜呜)

keepalive并不是TCP规范的一部分。在Host Requirements RFC罗列有不使用它的三个理由: 但自己的keepalive有这样的一个bug: 正常情况下,连接的另一端主动调用colse关闭连接,tcp会通知,我们知道了该连接已经关闭。 但是如果tcp连接的另一端突然掉线,或者重启断电,这个时候我们并不知道网络已经关闭。 而此时,如果有发送数据失败,tcp会自动进行重传。重传包的优先级高于keepalive,那就意 味着,我们的keepalive总是不能发送出去。 而此时,我们也并不知道该连接已经出错而中断。 在较长时间的重传失败之后,我们才会知道。即我们在重传超时后才知道连接失败.

05

不直接通知异常

c++: 在程序中表现为,当tcp检测到对端socket不再可用时(不能发出探测包,或探测包没有收到ACK的 * 响应包),select会返回socket可读,并且在recv时返回-1,同时置上errno为ETIMEDOUT.

06

启动定时器来检查

缺点:

  1. 对网络闪断情况处理不好
func (pthis *SocketClient) RecHeartBeating() {

    log.Println("RecHeartBeating begin ..")

    var ticker *time.Timer

    ticker = time.NewTimer(time.Second * 10)

    defer ticker.Stop()

    for {

        select {

        case _ = <-pthis.heartChannel:

            log.Println(pthis.conn.RemoteAddr().String(), "get message, keeping heartbeating...")

            //conn.SetDeadline(time.Now().Add(time.Duration(timeout) * time.Second))            ticker.Reset(time.Second * 10)

            break        case <-ticker.C:

            log.Println(" RecHeartBeating timeout!!!")

            pthis.userLeaveOp()

            pthis.conn.Close()

        }

    }

    log.Println("RecHeartBeating end ..")

}// 心跳计时,判断Client是否在设定时间内发来信息func (pthis *SocketClient) SendHeartBeating() {

    log.Println("SendHeartBeating begin ..")

    for {

        select {

        case <-time.After(time.Second * 5):

            log.Println(" SendHeartBeating!!!")

            data := "HeartBeating"            pthis.send(pthis.conn, heartReq, data)

        }

    }

    log.Println("SendHeartBeating end ..")



}  

07

自己实现

循环处理+sleep方式() 推荐方式

本章节内容:

大纲

心跳包实现考虑问题

1 是否能及时发现异常

2 明确通知业务层出现异常

计划:

原文发布于微信公众号 - 架构说(JiaGouS)

原文发表时间:2018-01-05

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏高性能服务器开发

服务器开发中网络数据分析与故障排查经验漫谈

一、 操作系统提供的网络接口 为了能更好的排查网络通信问题,我们需要熟悉操作系统提供的以下网络接口函数,列表如下: 接口函数名称接口函数描述接口函数签名soc...

36450
来自专栏宋凯伦的技术小栈

【菜鸟学Linux】Cron Job定期删除Log(日志)文件

  以前一直做Windows开发,近期的项目中要求使用Linux。作为小菜鸟一枚,赶紧买了一本经典书《鸟哥的Linux私房菜》学习。最近刚好有一个小任务 - 由...

305100
来自专栏Golang语言社区

用Go开发可以内网活跃主机嗅探器

源码相关: https://github.com/timest/goscan 文章关键词 go/golang gopacket 抓包 pcap/libpcap...

53690
来自专栏landv

烽火2640路由器命令行手册-02-接口配置命令

本文描述用于不同类型接口的基本命令,这些命令对应于手册包括的接口配置任务,有关配置要点,参考下面列出的各项内容。

14420
来自专栏windealli

socket常用函数知识点整理

调用close() 之后,进程不能再使用该描述符。 但是已经发送队列中的数据还是会继续发送,等到发送回再发起四次挥手。

31620
来自专栏Java进阶架构师

一篇文章带你详解 HTTP 协议(上)

利用 TCP/IP 协议族进行网络通信时,会通过分层顺序与对方进行通信。发送端从应用层往下走,接收端则从链路层往上走。如下:

13040
来自专栏杨龙飞前端

使用webpack打包vue工程

19230
来自专栏杨龙飞前端

使用webpack打包vue工程

24870
来自专栏我的博客

CSRF原理和防范

一.CSRF CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/sessi...

45080
来自专栏互联网杂技

入门webpack(下)

插件(Plugins) 插件(Plugins)是用来拓展Webpack功能的,它们会在整个构建过程中生效,执行相关的任务。 Loaders和Plugins常常被...

33060

扫码关注云+社区

领取腾讯云代金券