一,TCP,UDP协议在OSI模型中属于传输层,传输层的功能定义了传输数据的协议和端口号。IP协议属于网络层,网络层的功能将从下层接收到的数据进程IP地址的封装与解封装。
TCP协议的六个标志位:
URG为紧急数据标志,如果URG为1,表示本数据包中包含紧急数据。此时紧急数据指针表示的值有效,它表示在紧急数据之后的第一个字节的偏移值(即紧急数据的总长度)。
ACK为确认标志位。如果ACK为1,表示数据包中的确认号有效。
PSH位,表示强迫数据传输。
RST标志位用来复位一条连接。当RST=1时,表示出现严重错误,必须释放连接,然后再重新建立。
SYN标志位用来建立连接,如果SYN=1而ACK=0,表明它是一个连接请求;如果SYN=1且ACK=1,则表示同意建立一个连接。
FIN为1时,表示数据已经发送完毕,希望释放连接。
二,下面几种情况是不合法的标志位组合。
1、所有标志位都为0。
2、SYN和FIN同时被置1。
3、SYN和RST同时被置1。
4、FIN和RST同时被置1。
5、FIN位被置1,但ACK位没有被置1。
6、PSH位被置1,但ACK位没有被置1。
7、URG位被置1,但ACK位没有被置1。
三,TCP的三次握手与状态
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
在这里引入一个常见的syn攻击(dos攻击):客户端发送大量syn请求,然后服务端发送syn/ack,但是客户端并不回应ack,当服务器未收到客户端的确认包时,重发请求包,一直到超时,才将此条目从未连接队列删除。因此服务端维持大量syn请求,配合IP欺骗,SYN攻击能达到很好的效果,通常,客户端在短时间内伪造大量不存在的IP地址,向服务器不断地发送syn包,服务器回复确认包,并等待客户的确认,由于源地址是不存在的,服务器需要不断的重发直至超时,这些伪造的SYN包将长时间占用未连接队列,正常的SYN请求被丢弃,目标系统运行缓慢,严重者引起网络堵塞甚至系统瘫痪。如果服务端syn_rcvd个数超出正常的时,有可能被攻击。
查看在LINUX环境下某个端囗的未连接队列的条目数:
#netstat -nt |grep SYN_RECV |grep :22 |wc -l
四,tcp四次断开
当服务端主动发达fin,等待客户端的fin时,服务端需要在内存中维持这个状态,如果控制客户端永久不发送。则当内存耗尽时将无法再响应别的请求,因此fin_wait_2是很危险的状态,所以最好不要让服务端主动断开,而且每个应用程序能打开的套接字有限,会导致别的请求无法再响应。
五,tcp整个连接状态图,这图是简化的,正常关闭情况下的流程是这样的。
六,解释各种状态:
closed:表示初始状态。
listen:表示socket处于监听状态,因此服务端是被动启动。
syn_rcvd:表示服务端接收到客户端的syn报文。
syn_sent:表示客户端已发送syn报文,因此客户端是主动启动。当客户端需要请求资源时,会执行socket,首先发送syn报文,随即进程syn_sent状态。
established:表示已经完成三次握手,咱们开始谈恋爱吧
fin_wait_1:客户端发送完fin后的状态。
fin_wait_2:客户端收到服务端的ack后。
time_wait:客户端发送完ack后。并在此状态等待2ms后,自动进入closing状态。
close_wait:收到客户端fin,并发送ack。
last_ack:服务端等对方的ack,当收到ack后,表示咱俩分手,永不见面。
七,在TCP/IP原始的图片中,可能还会出现下面情况
1,服务器端主动关闭,establelished(发送fin)--->fin_wait_1(等待客户端的ack)-->fin_wait_2(等待客户端的fin,此时fin_wait_2可以永久存在内存中)--time_wait
客户端被动关闭:establelished--->close_wait(发送ack,fin)---last_ack(等待对方的ack包,如果收到ack)--->closed
正常情况下,fin_wait_2存在的时间很短暂,因此,图又可以简化成这样。
2,假设都是服务端提供服务,都同时关闭,则此时不区分服务端与客户端
establelished--->fin_wait_1(同时发送ack,fin)--->closeding--->time_wait