TCP连接整理

168 阅读6分钟

现在在一家公司做一些长连接开发,涉及到netty,对于计算机底层的知识掌握要求高一些,至此也做一些巩固学习,提高一下自己

关键词

  1. 往返时延RTT(Round-Trip-Time)

  2. 超时重传时间 RTO

  3. 发送方时间戳(TS value)、回显时间戳(TS Echo Reply)TSR和 TSECR

  4. 序列号回绕(PAWS)

  5. 路径最大传输单元 MTU

  6. 初始序列号(Initial Sequence Number, ISN)

  7. TCP 最大段大小(Max Segment Size,MSS)

  8. 什么是半连接队列,什么是SYN FLOOD攻击

   客户端伪造大量的IP发送SYN包,服务端回复的ACK + SYN去到了一个未知的IP地址,势必会造成服
   务端大量的连接处于SYN_RCVD状态,而服务器的半连接队列大小也是有限的,如果半连接队列满了,
   也会出现无法处理正常请求的情况
  1. 说说TCP快速打开(TFO)的原理
TCP FAST OPEN ,TFO是在原来TCP协议上的扩展协议,他主要是在发送第一个SYN包的时候就开始传输
数据了,要求之前客户端、服务端就完成过三次握手
TFO分为两个阶段,请求Fast Open Cookie 和真正开始TCP Fast Open
  1. TCP时间戳的作用
TCP时间戳包括 类别、长度、发送时间戳、回显时间戳

计算往返时延RTT(Round-Trip-Time)

TCP 在发送一个包时,会记录这个包的发送的时间 t1,用收到这个包的确认包时 t2 减去 t1 就可以得到这次的 RTT
  1. TCP的超时重传时间是如何计算的
TCP具有超时重传机制,就是间隔一段时间没有收到数据包的回复的时候,重传这个数据包,
超时重传时间 RTO

TCP 发送数据后会启动一个定时器,等待对端确认收到这个数据包。如果在指定的时间内没有收到 ACK 
确认,就会重传数据包,然后等待更长时间,如果还没有收到就再重传,在多次重传仍然失败以后,TCP 
会放弃这个包。后面我们讲到超时重传模块的时候会详细介绍这部分内容。

image.png

  1. 面向连接,无连接的含义
面向连接(connection-oriented):面向连接的协议要求正式发送数据之前需要通过「握手」建立一个逻辑连接,结束通信时也是通过有序的四次挥手来断开连接。

无连接(connectionless):无连接的协议则不需要

TCP 是一种字节流(byte-stream)协议,流的含义是没有固定的报文边界。

初始序列号(Initial Sequence Number, ISNTCP 使用确认号(Acknowledgment number, ACK)来告知对方下一个期望接收的序列号,小于此确认号的所有字节都已经收到。


`netstat -i` 可以查看网卡的 mtu

分层结构中每一层都有一个唯一标识,比如链路层的 MAC 地址,IP 层的 IP 地址,传输层是用端口号。

凡是消耗序列号的 TCP 报文段,一定需要对端确认。如果这个段没有收到确认,会一直重传直到达到指定的次数为止。

image.png

image.png

image.png

  1. Linux 命令
netstat 很强大的网络工具,可以用来显示套接字的状态
    -a命令可以输出所有的套接字
    -t 选项可以只列出 TCP 的套接字,也可也用--tcp
    -u 选项用来指定显示 UDP 的连接,也可也用--udp 示例输出:
    -l 选项用来指定处于 LISTEN 状态的连接,也可以用--listening 示例输出:
    -n 禁用端口 和 IP 映射
    -p 使用 -p命令可以显示连接归属的进程信息

    netstat -antp | grep ":8080" | grep ESTABLISHED
    netstat -ant | awk '{print $6}' | uniq -c | sort -n
    使用 awk 截取出状态行,然后用 sort、uniq 进行去重和计数即可

netcat
    nc -l -p 9091 l的含义是 listen。 用 nc 来当聊天服务器
    nc 10.211.55.5 9090
    nc -zv [host or ip] [port]  
    其中 -z 参数表示不发送任何数据包,tcp 三次握手完后自动退出进程。有了 -v 参数则会输出更
    多详细信息(verbose)。
    
除了我们熟知的 HTTP 协议,还有下面这些非常常用的应用层协议

    -   域名解析协议 DNS
    -   收发邮件 SMTP 和 POP3 协议
    -   时钟同步协议 NTP
    -   网络文件共享协议 NFS
    
TCP 是一个可靠的(reliable)、面向连接的(connection-oriented)、基于字节流(byte-stream)、全双工的(full-duplex)协议。  

TCP 要想在 IP 基础上构建可靠的传输层协议,必须有一个复杂的机制来保障可靠性。 主要有下面几个方面:

    -   对每个包提供校验和
    -   包的序列号解决了接收数据的乱序、重复问题
    -   超时重传
    -   流量控制、拥塞控制

因为网络层(IP 层)不保证包的顺序,TCP 协议利用序列号来解决网络包乱序、重复的问题,以保证数据包以正确的顺序组装传递给上层应用。

TCP 使用确认号(Acknowledgment number, ACK)来告知对方下一个期望接收的序列号,小于此确认号的所有字节都已经收到。

最常见的有下面这几个:

-   SYN(Synchronize):用于发起连接数据包同步双方的初始序列号
-   ACK(Acknowledge):确认数据包
-   RST(Reset):这个标记用来强制断开连接,通常是之前建立的连接已经不在了、包不合法、或者实在无能为力处理
-   FIN(Finish):通知对方我发完了所有数据,准备断开连接,后面我不会再发数据包给你了。
-   PSH(Push):告知对方这些数据包收到以后应该马上交给上层应用,不能缓存起来

端口号被划分成以下 3 种类型:

    熟知端口号(well-known port)
    已登记的端口(registered port)
    临时端口号(ephemeral port)

我们知道客户端主动发起请求 connect 时,操作系统会为它分配一个临时端口(ephemeral port)。
在 linux 上 这个端口的取值范围由 /proc/sys/net/ipv4/ip_local_port_range 文件的值决定,在我的 CentOS 机器上,临时端口的范围是 32768~60999。



有两种典型的使用方式会生成临时端口:
	调用 bind 函数不指定端口
	调用 connect 函数

除了交换彼此的初始序列号,三次握手的另一个重要作用是交换一些辅助信息,
比如最大段大小(MSS)、窗口大小(Win)、窗口缩放因子(WS)、是否支持选择确认(SACK_PERM)等,


tcpdump -i any

-i表示指定哪一个网卡,any 表示任意
有哪些网卡可以用 ifconfig 来查看
如果只想查看 eth0 网卡经过的数据包,就可以使用tcpdump -i eth0来指定。

过滤源地址、目标地址:src、dst
	如果只想抓取主机 10.211.55.10 发出的包
	sudo tcpdump -i any src 10.211.55.10
	如果只想抓取主机 10.211.55.10 收到的包
	sudo tcpdump -i any dst 10.211.55.10


过滤端口:port 选项
	抓取某端口的数据包:port 选项比如查看 80 端通信的数据包
	sudo tcpdump -i any port 80
	如果只想抓取 80 端口收到的包,可以加上 dst


	sudo tcpdump -i any dst port 80