一、课程信息
打卡时间:2022.8.4
课程名称:C/C++气象数据中心实战,手把手教你做工业级项目
章节名称:开发基于tcp协议的文件传输子系统
讲师: 长歌_吴从周
二、今日课程
课程内容:(1)解决TCP报文粘包/分包的问题 (2)学习使用封装的socket函数
三、学习心得
3.1 粘包/分包问题
粘包和分包产生的原因主要有三种:滑动窗口、MSS/MTU限制、Nagle算法。
滑动窗口造成粘包/分包的原因是:TCP流量控制主要使用滑动窗口,滑动窗口是接受数据段使用的窗口大小,用来告诉发送方接收端的缓存大小,以此来控制发送端发送数据的大小,达到流量控制的目的。如果接收方处理信号不及时,那么发送方发送的报文会被缓存到接收缓冲区中,当缓存区缓存多个报文时,对于接收方而言就发生了粘包。同理,当接收方的接受窗口较小时,小于发送方一个完整报文的长度时,发送方需要将报文进行拆分,这就发生了分包。
MSS/MTU限制造成粘包/分包的原因是:当发送方发送数据大于MSS时就发生了分包。
Nagle算法造成粘包/分包的原因是:TCP/IP协议中,无论发送多少数据,总是要在DATA前加上协议头,同时对方接收到数据,也需要发送ACK表示确认。如果发送方每次只是发送少量数据无疑会带来巨大开销,Nagle算法就是为了尽可能发送大块数据,避免网络中充斥着许多小数据块。因此较小的数据包会被缓存在发送缓冲区,这就造成了粘包。使用原生的send和revc函数会造成粘包和分包的问题。
如何解决粘包/分包问题呢?
采用自定义的报文格式:数据长度+报文内容 0010abcdefghi
3.2 封装的socket函数调用细节
CTcpClient类封装了socket的api,方便使用,可以将更多的精力放在业务逻辑上面。需要注意的是,一般需要在TCP进程中忽略SIGPIPE信号。在TCP通信中,当通信的双方中的一方close一个连接时,若另一方接着发数据,根据TCP协议的规定,会收到一个RST响应报文,若再往这个服务器发送数据时,系统会发出一个SIGPIPE信号给进程,告诉进程这个连接已经断开了,不能再写入数据。同时我们在服务器上需要开启SO_REUSEADDR选项,一般而言父进程负责监听socket,fork出的子进程用于处理,当父进程终止后,TCP客户端处于 timewait状态,子进程继承父进程的socket,需要等到子进程终止后才能使用这个socket。SO_REUSEADDR 这个套接字选项通知内核,如果端口忙,但TCP状态位于 TIME_WAIT ,可以重用端口。如果端口忙,而TCP状态位于其他状态,重用端口时依旧得到一个错误信息,指明"地址已经使用中"。如果你的服务程序停止后想立即重启,而新套接字依旧使用同一端口,此时SO_REUSEADDR 选项非常有用。
四 课程学习截图
共同学习,写下你的评论
评论加载中...
作者其他优质文章