在TCP协议的通信过程中,由于其面向流的特性,数据在传输过程中可能会发生粘包现象,即多个发送的数据包被接收方一次性接收,导致应用层无法正确解析数据。
1.粘包现象概述
TCP协议为了保证传输效率,可能会将多次send
调用发送的数据合并在一个TCP报文中发送出去。这样,接收方在读取时就可能遇到粘包问题,即无法直接从字节流中识别出各个独立的数据包。
粘包处理方式:
1.自己规定数据之间的间隔符,"\aa";
2.指定要发送的数据长度
3.自己将数据打包 struct
2.tcp数据的收发函数
可以用write和read实现,也有专门的函数来实现该功能,下面对这两个函数进行简单介绍。
send
函数原型为: ssize_t send(int sockfd, const void *buf, size_t len, int flags);
该函数与sendto函数前面参数均相同最后一个参数,flags 是一个选项参数,它可以影响发送的行为。
recv
函数原型为: ssize_t recv(int sockfd, void *buf, size_t len, int flags);
fiags:一般设置为0
MSG_PEEK:窥视传入的数据。 数据被复制到缓冲区中,但不会从输入队列中删除。
MSG_OOB:处理带外(OOB)数据。
MSG_WAITALL:
仅当发生以下事件之一时,接收请求才会完成:
调用方提供的缓冲区已完全满。
连接已关闭。
该请求已被取消或发生错误。
3.netstat命令的常见使用方式
4.抓包
tcp报文段的首部格式
TCP虽然是面向字节流的,但TCP传送的数据单元却是报文段。一个TCP报文段分为
首部和数据两部分,而TCP的全部功能都体现在它首部中各字段的作用。
TCP首部的最小长度是20字节。
(1)源端口和目的端口:各占2个字节,分别写入源端口号和目的端口号。
(2)序号:占4字节。在一个TCP连接中传送的字节流中的每一个字节都按顺序编号。也称“报文段序号”。
(3)确认号:占4字节,是期望收到对方下一个报文段的第一个数据字节的序号。
(4)数据偏移:占4位,它指出TCP报文段的数据起始处距离TCP报文段的起始处有多远。这个字段实际上是指出TCP报文段的首部长度。数据偏移最大值为60字节。这也是tcp首部的最大长度
(5)保留:占6位,保留为今后使用,但目前应置为0。
(6)6个控制位
紧急URG(URGent):为1有效;高优先级数据。与紧急指针字段配合使用。
确认ACK (ACKnowl egment):1有效,0无效。建立连接后,所有ACK都置1。
推送PSH (PuSH):为1时发送方创建一个报文段发出,接收方收到PSH=1的报文段,就尽快交付给应用进程,不用等待缓存填满后再交付。
复位RST (ReSeT) :当RST = 1时, 表明 TCP连接中出现严重差错(如由千主机崩溃或其他原因),必须释放连接, 然后再重新建立运输连接。 RST詈1还用来拒绝一个非法的报文段或拒绝打开一个连接。 RST也可称为重建位或重置位。
同步SYN (SYNchronization) :在连接 建立时用来同步序号。 当SYN= 1而ACK
= 0时, 表明这 是一个连接请求报文段。 对方若同意建立连接, 则应在响应的报文段中使
SYN= 1和ACK= 1。 因此, SYN置为1就表示这是一个连接请求或连接接受报文。
终止FIN (FINis, 意思是 “ 完 "、"终 " ): 用来释放一个连接。 当FIN= 1时, 表明此报文段的发送方的数据已发送完毕, 并要求释放运输连接。
窗口:占2字节。是指接收方窗口。窗口字段明确指出了现在允许对方发送的数据量。 窗口值是经常在动态变化着。之所以要有这个限制, 是因为接收方的数据缓存空间是有限的。 窗口值作为接收方让发送方设置其发送窗口的依据。
(7)检验和:占2字节。检验和字段检验的范围包括首部和数据这两部分。
(8)紧急指针:占2字节。1有效。
(9)选项:长度可变, 最长可达40字节。 当没有使用选项时, TCP的首部长度是 20字节。、
抓包工具在虚拟机的安装方式:
//ssh登录 ubuntu 需要安装以下的服务
sudo apt-get install openssh-server openssh-client
sudo apt install wireshark
sudo wireshark
抓包观察三次握手和四次挥手