TCP编程流程和粘包

news2024/9/23 15:20:41

目录

1、TCP编程流程

 2、粘包


1、TCP编程流程

 

socket() 是创建套接字,返回值为监听套接字描述符,有了套接字才能通过网络进行数据的传输。创建套接字的参数要指定服务类型,TCP协议使用的是流式服务(SOCK_STREAM)。

bind() 是指定套接字使用的IP和端口。IP地址 是自己主机的地址。端口 是一个16位整型值, 一般0~1024为知名端口,一般用户不能随便使用;1024~4096为保留端口,一般不使用;4096以上为临时端口,可以使用。在Linux系统上,1024以内的端口号只有root用户可以使用。

listen() 是创建监听队列。监听队列有两种,一个是存放未完成三次握手的连接,一种是存放已完成三次握手的连接。该函数的第二个参数在Linux系统上是指已完成三次握手队列的长度,在Unix系统上是未完成和已完成三次握手队列总和的大小。

accept() 是处理放在 listen() 创建的已完成三次握手队列中的连接。每处理一个连接,accept()返回一个该连接对应的连接套接字描述符,如果已完成三次握手队列为空,则accept阻塞。

 

connect() 一般由客户端程序执行,需要指定连接的服务端的IP和端口。该方法执行后,会进行三次握手,建立连接

三次握手(建立连接)

send() 是用来向TCP连接的对端发送数据。send()执行成功,说明成功将数据写入发送端的发送缓冲区中,并不能说明已经发到对端。返回值为实际写入发送缓冲区的数据长度。

recv() 是用来接收TCP连接的对端发送的数据。recv()从自己的接收缓冲区中读取数据,如果接收缓冲区中没有数据,就会阻塞。返回值为实际读取的字节数。

recv()返回值为0是对端关闭TCP连接的唯一标识。

close() 可用来关闭文件的,该处用于关闭套接字和TCP连接。

关闭TCP链接:自己端执行该方法后,在对端未执行close()时,进行两次挥手,此时处于半连接状态;当对端也执行close()后,再进行后两次挥手,最终完成四次挥手。

四次挥手(断开连接)

 2、粘包

对6.2服务端代码中的recv()函数的参数从127改为1,即一次recv一个字符。

客户端发送一个 "hello" ,服务端将会把hello每个字符换行打印一次,客户端收到一个 "ok" ;当客户端再发送数据后,将会收到四个 "ok" 。如下图:

 

 

原因:首先明确程序的循环运行速度要小于服务端将数据从其发送缓冲区传递到客户端的接收缓冲区。recv()和send()都是从接收缓冲区和发送缓冲区中读取数据,并不意味着把数据发给对方或者从对方处接收到数据。

当服务端recv()第一个字符 ‘h’ 后,此时客户端的recv()正处于阻塞状态(客户端的接收缓冲区为空),send()一个 "ok" 到发送缓冲区并传递给客户端的接收缓冲区,还没等到服务端recv()第二个字符 ‘e’ 后send()第二个 "ok" ,客户端就已经recv()了其接收缓冲区中的 “ok” ,此时客户端的接收缓冲区只有一个 “ok” 。客户端recv()后阻塞在fgets()函数处,等待输入数据。等待过程中,服务端也已经将剩下的四个字符对应的四个 "ok" 陆陆续续发送到客户端的接收缓冲区中,当客户端刚recv()第二个数据后,就会立即读取接收缓冲区中的四个 "ok" ,将其打印出来。

查看缓冲区的数据字节大小命令:netstat -natp

 

 

出现这种数据粘连在一起无法区分第几次发送的情况即为粘包

粘包的概念:TCP粘包就是指发送方发送的若干包数据到达接收方时粘成了一包

产生粘包的原因:

1、TCP是基于字节流的,虽然应用层和传输层之间的数据交互是大小不等的数据块,但是TCP把这些数据块仅仅看成一连串无结构的字节流,没有边界; 2、在TCP的首部没有表示数据长度的字段,基于上面两点,在使用TCP传输数据时,才有粘包或者拆包现象发生的可能。

粘包/拆包发生的原因:

发生TCP粘包或拆包有很多原因,现列出常见的几点: 1、要发送的数据大于TCP发送缓冲区剩余空间大小,将会发生拆包。 2、待发送数据大于MSS(最大报文长度),TCP在传输前将进行拆包。 3、要发送的数据小于TCP发送缓冲区的大小,TCP将多次写入缓冲区的数据一次发送出去,将会发生粘包。 4、接收数据端的应用层没有及时读取接收缓冲区中的数据,将发生粘包。

TCP 字节流的特点:发送端执行的写操作次数和接收端执行的读操作次数之间没有任何数量关系,应用程序对数据的发送和接收是没有边界限制的。

 

粘包对于数据下载没有影响,只需要将数据全部收到就可以;而在交互时需要发送次数与接收次数对应。

粘包的简单解决办法:

1、发送端给每个数据包添加包首部,首部中应该至少包含数据包的长度,这样接收端在接收到数据后,通过读取包首部的长度字段,便知道每一个数据包的实际长度了。

2、在数据前后加上标志,对方接收到数据后进行检查数据是否完整。3、发送端将每个数据包封装为固定长度(不够的可以通过补0填充),这样接收端每次从接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/758847.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

用Matlab听音乐 - 动态频谱

文章目录 高帧率版本效果: 定时器版本music_play主函数:定时器回调函数:效果: 高帧率版本 由于matlab这款科学计算软件本身庞大略显笨重,执行代码的速度受当前系统影响,很难做到严格定时仿真(造成音画不同步&#xff…

互联网行业真的不行了吗?

文章目录 前言一、起因二、互联网真的完了吗?三、是不是要转行?四、十年磨一剑五、统一回复 前言 英雄算法联盟 - 七月集训 已经开始 16 天,八月算法集训 将于 08月01日 正式开始,目前已经提前开始报名,报名方式参见&a…

英国24所顶尖大学撤销禁令,更新AI使用规定!

自从ChatGPT展现了其高超的AI技术后,备受全球年轻人的喜爱。ChatGPT功能多样化,可以节省查阅复杂文献的时间、编写简单的Python代码、辅助学生理解知识点... 同时,ChatGPT引发的学术不诚信问题也让各大院校头疼不已。 连续数月以来&#xff…

js 浮点位数超过17位乘以10^18,精度丢失问题

我有一个浮点型 var num 9.963407954080194743 用num * (10 ** 18) 计算得出的结果是9963407954080195000, 但是我想要得到的结果是9963407954080194743 问ChatGPT问题得以解决: GPT提供的代码: import Big from big.js;const num1 new Big(9.9634…

从输入URL到页面渲染的整个过程

从输入URL到页面渲染的整个过程 1.DNS解析,把url中的域名解析成对应的IP地址。如果本地DNS缓存没有响应的记录,则会向DNS发送请求,获取相应的IP地址。 2.浏览器使用获取到的目标服务器的IP地址,通过TCP/IP协议与服务器建立连接&a…

python-web开发(Djaongo)课程基本内容

python-web开发(Djaongo)课程基本内容及其前置技术 参考内容: 【最新Python的web开发全家桶(django前端数据库)】 https://www.bilibili.com/video/BV1rT4y1v7uQ/?share_sourcecopy_web&vd_source84fd4883bb478d0…

CDA数据分析系01 anaconda

简介 数据处理集成包,不局限于python 创建一个新的environment conda create --name python34 python3.4 激活一个environment activate python34 # for windows conda的package管理 类似pip,conda install xxxx 查看已安装的python包 conda list…

利用技术优势:程序员如何通过互联网自媒体项目实现财务自由?

作为程序员,通过互联网自媒体项目实现财务自由是一个很好的选择。以下是一些技术优势的利用方法: 选择适合的自媒体平台:在互联网上有许多不同类型的自媒体平台,如博客、YouTube、Podcast等。选择适合你技术背景和兴趣的平台&…

手机忘记密码怎么办? 帮你快速解锁手机的十大软件请收好

有许多不同类型的手机锁,这些锁对于手机的用户或所有者来说可能非常烦人和恼人。这些锁可称为手机锁、SIM 锁、主锁或运营商锁。这些锁实际上是手机的实际限制。 为了仅在有限的国家/地区阻止电话访问,该区域之外的任何其他人都无法使用。 手机解锁如何…

极速上手k8s,Kubernetes 从入门到摸鱼系列-实践篇

大家好,我是比特桃。本文为《极速上手k8s,Kubernetes 从入门到摸鱼系列》的实战篇,旨在快速上手k8s。如没有阅读过k8s相关理论的朋友,可以先阅读理论篇。 1. 实践环境 k8s 的意义在于分布式大规模容器编排,所以如果我…

第一百零八天学习记录:C++基础:文件操作

C中对文件操作需要包含头文件<fstream> 操作文件的三大类&#xff1a; 1、ofstream:写擦破自评 2、ifstream:读操作 3、fstream:读写操作 文本文件 写文件 写文件步骤如下&#xff1a; 1、包含头文件 #include <fstream>2、创建流对象 ofstream ofs; 3、打开文…

Vue2笔记

Vue2 前端 语雀 (yuque.com) vue3: https://github.com/Panyue-genkiyo/vue3-learning vue2依据脚手架:https://github.com/Panyue-genkiyo/vue-advance vue基础不依赖脚手架:https://github.com/Panyue-genkiyo/vue-learning Vue 是一套用于构建用户界面的 渐进式框框架…

B2B2C多用户商城软件功能清单

多用户B2B2C是如今企业搭建电商平台比较火热模式&#xff0c;B2B2C包含了B2B与B2C这两者模式的特点&#xff0c;是非常具有发展前景的商城系统&#xff0c;那么一个完善的多用户B2B2C商城系统应该包含哪些主要功能呢?加速度jsudo一起来看看吧! 商品模块功能&#xff1a; 包括…

【深度剖析】 堆排序为什么不稳定?!

文章目录 零、前言一、什么是稳定性&#xff1f;二、不稳定的地方在哪里&#xff1f; 零、前言 最近做面试题中&#xff0c;遇到一些平时学习中比较少注意到的问题&#xff0c;记录下来以便后来者学习讨论。 对 堆排序 不熟悉的 可以参考 &#x1f449;&#x1f449;&#x1f4…

TortoiseGit 入门指南07:创建分支

Git 的 分支 出了名的好用。其它的版本控制系统也提供分支&#xff0c;但在易用度上&#xff0c;只有两类版本控制系统&#xff1a;一种是 Git&#xff0c;一种是其它。 Bob 大叔在《匠艺整洁之道》中写道&#xff1a; 我曾经坚持拒绝分支。在使用 CVS 和 Subversion 的时候&a…

检测到目标X-Content-Type-Options响应头缺失

详细描述 X-Content-Type-Options HTTP 消息头相当于一个提示标志&#xff0c;被服务器用来提示客户端一定要遵循在 Content-Type 首部中对 MIME 类型 的设定&#xff0c;而不能对其进行修改。这就禁用了客户端的 MIME 类型嗅探行为&#xff0c;换句话说&#xff0c;也就是意味…

Dynamic-SLAM2019论文翻译

Dynamic-SLAM:动态环境下基于深度学习的语义单目视觉定位与建图 摘要-传统SLAM框架在动态环境下工作时&#xff0c;由于受到动态对象的干扰&#xff0c;性能较差。为了解决动态环境下的SLAM问题&#xff0c;利用深度学习在目标检测中的优势&#xff0c;提出了一种语义同步定位…

Science Advances|上海交大王风平团队揭示深古菌与早期地球协同演化历史

Research Article&#xff0c;2023-7-5&#xff0c;Science Advances&#xff0c; [IF 13.6] 原文链接&#xff1a;https://www.science.org/doi/full/10.1126/sciadv.adf5069 第一作者&#xff1a;侯佳林 通讯作者&#xff1a;王风平&#xff0c;王寅炤 - 摘要 - 近日&#xf…

C++——友元

友元的定义 C 中的友元&#xff08;friend&#xff09;是一种允许非成员函数或类访问另一个类的私有或保护成员的机制。友元可以是一个普通的非成员函数、另一个类或整个类的所有成员函数。 什么情况下需要友元 现在尝试去重载operator<<&#xff0c;然后发现没办法将o…

vscode 配置ssh 免密登录 多台服务器

0、下载vscode Visual Studio Code - Code Editing. Redefined 之前一直用pycharm 但是好像社区免费版本不能连接服务器&#xff0c;还要本地同步代码&#xff0c;比较繁琐&#xff0c;因此改用vscode。 1、添加ssh 添加后可以尝试登录&#xff0c;确认下账号密码&#xff0…