在TCP层,有个FLAGS字段,这个字段有以下几个标识:
SYN 建立连接;
FIN 关闭连接;
ACK 响应;
PSH 有数据传输;
RST 连接重置;URG。
其中,ACK是可能与SYN,FIN等同时使用的,比如SYN和ACK可能同时为1,它表示的就是建立连接之后的响应;如果只是单个的一个SYN,它表示的只是建立连接。但SYN与FIN是不会同时为1的。RST一般是在FIN之后才会出现为1的情况,表示的是连接重置。
TCP(Transmission Control Protocol)传输控制协议 的三次握手:
TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接:
位码即tcp标志位,有6种标示:SYN(synchronous建立联机) ACK(acknowledgement 确认) PSH(push传送) FIN(finish结束) RST(reset重置) URG(urgent紧急)Sequence number(顺序号码) Acknowledge number(确认号码)
第一次握手:主机A发送位码为syn=1,随机产生seq number=1234567的数据包到服务器,主机B由SYN=1知道,A要求建立联机;主机A进入SYN_SEND状态
第二次握手:主机B收到请求后要确认联机信息,向A发送ack number=(主机A的seq+1),syn=1,ack=1,随机产生seq=7654321的包;主机B进入SYN_RECV状态
第三次握手:主机A收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确,主机A会再发送ack number=(主机B的seq+1),ack=1,主机B收到后确认seq值与ack=1则连接建立成功。主机A和主机B进入ESTABLISHED状态,开始传送数据。
四次挥手
TCP协议是一种面向连接的、可靠的、基于字节流的运输层通信协议。TCP是全双工模式,这就意味着,当主机1发出FIN报文段时,只是表示主机1已经没有数据要发送了,主机1告诉主机2,它的数据已经全部发送完毕了;但是,这个时候主机1还是可以接受来自主机2的数据;当主机2返回ACK报文段时,表示它已经知道主机1没有数据发送了,但是主机2还是可以发送数据到主机1的;当主机2也发送了FIN报文段时,这个时候就表示主机2也没有数据要发送了,就会告诉主机1,我也没有数据要发送了,之后彼此就会愉快的中断这次TCP连接。如果要正确的理解四次分手的原理,就需要了解四次分手过程中的状态变化。
图解
TCP的几个重要参数介绍
1.TCP_NODELAYED
默认情况下, TCP发送数据采用Nagle算法.。Nagle算法是解决小数据的频繁发送问题,比如1个字节的数据,在封包后会加上几十字节的首部,相当浪费资源。Nagle的做法是发送方发送的数据不会立即发出,而是先放在缓冲区,等待缓冲区达到一定的大小,或者是缓冲达到一定的时间后再一批发出。 发送完一批数据后, 会等待接收方对这批数据的回应,然后再发送下一批数据.。Negle算法适用于发送方需要发送大批量数据, 并且接收方会及时作出回应的场合, 这种算法通过减少传输数据的次数来提高通信效率。
如果发送方持续地发送小批量的数据, 并且接收方不一定会立即发送响应数据, 那么Negle算法会使发送方运行很慢。对于GUI 程序, 如网络游戏程序(服务器需要实时跟踪客户端鼠标的移动), 这个问题尤其突出.。客户端鼠标位置改动的信息需要实时发送到服务器上,由于Negle算法采用缓冲, 大大减低了实时响应速度, 导致客户程序运行很慢。
我们可以通过设置TCP_NODELAYED来禁用Negle算法。
2.so_keepalive
so_keepalive是TCP的心跳机制,保持连接检测对方主机是否崩溃,避免(服务器)永远阻塞于TCP连接的输入。设置该选项后,如果2小时内在此套接口的任一方向都没有数据交换,TCP就自动给对方 发一个保持存活探测分节(keepalive probe)。这是一个对方必须响应的TCP分节。它会导致以下三种情况:
- 对方接收一切正常:以期望的ACK响应,2小时后,TCP将发出另一个探测分节。
- 对方已崩溃且已重新启动:以RST响应。套接口的待处理错误被置为ECONNRESET,套接 口本身则被关闭。
- 对方无任何响应:源自berkeley的TCP发送另外8个探测分节,相隔75秒一个,试图得到一个响应。在发出第一个探测分节11分钟15秒后若仍无响应就放弃。套接口的待处理错误被置为ETIMEOUT,套接口本身则被关闭。如ICMP错误是“host unreachable(主机不可达)”,说明对方主机并没有崩溃,但是不可达,这种情况下待处理错误被置为 EHOSTUNREACH。
SO_KEEPALIVE有三个参数,其详细解释如下:
tcp_keepalive_intvl,保活探测消息的发送频率。默认值为75s。发送频率tcp_keepalive_intvl乘以发送次数tcp_keepalive_probes,就得到了从开始探测直到放弃探测确定连接断开的时间,大约为11min。
tcp_keepalive_probes,TCP发送保活探测消息以确定连接是否已断开的次数。默认值为9(次)。值得注意的是,只有设置了SO_KEEPALIVE套接口选项后才会发送保活探测消息。
tcp_keepalive_time,在TCP保活打开的情况下,最后一次数据交换到TCP发送第一个保活探测消息的时间,即允许的持续空闲时间。默认值为7200s(2h)。
3.backlog
对于TCP连接,内核维护两个队列:
1. 未完成连接的队列,此队列维护着那些已收到了客户端SYN分节信息,等待完成三路握手的连接,socket的状态是SYN_RCVD。
2. 已完成的连接的队列,此队列包含了那些已经完成三路握手的连接,socket的状态是ESTABLISHED,但是等待accept。
backlog
backlog在linux2.2之后表示队列2(已经完成连接,等待accept调用)。
backlog的值太小会导致在大量连接的时候不能处理,丢弃客户端发送的ack,此时如果客户端认为连接建立继续发送数据,就会出现满请求。backlog过大会导致连接积压,性能下降。
调用listen监听的时候可以设置backlog的值,backlog 并不是按照你调用listen的所设置的backlog大小,实际上取的是backlog和somaxconn的最小值。somaxconn的值定义在/proc/sys/net/core/somaxconn,默认是128,可以把这个值修改更大以满足高负载需求。
syn_backlog
syn_backlog指队列1(半连接SYN_RCVD阶段)。
这个值在/proc/sys/net/ipv4/tcp_max_syn_backlog ,可以对其进行调整。但是一般情况下处于syn_rcvd阶段的不会太多,除非遇到SYN_FLOOD攻击。
SYN FLOOD:
SYN Flood利用的是TCP协议缺陷,发送大量伪造的TCP连接请求,从而使得被攻击方资源耗尽(CPU满负荷或内存不足)的攻击方式。在被攻击主机用netstat可以看见80端口存在大量的半连接状态(SYN_RECV),用tcpdump抓包可以看见大量伪造IP发来的SYN连接,S也不断回复SYN+ACK给对方,可惜对方并不存在(如果存在则S会收到RST这样就失去效果了),所以会超时重传。这个时候如果有正常客户A请求S的80端口,它的SYN包就被S丢弃了,因为半连接队列已经满了,达到攻击目的。