Socket编程 Tcp和粘包
大多数程序员都要接触网络编程,Web开发天天和http打交道。稍微底层一点的程序员,就是TCP/UDP 。
对程序员来说,Tcp/udp的核心是Socket编程。
我的浅薄的观点---------理解socket tcp编程除了基础知识外,1是异步IO模型,2是粘包。
今天讨论下粘包。 便于理解用同步接口来实现 。本文侧重于代码来探讨和解决问题。理论可以看其他博客
先来思考一个问题:如下代码,发送端每次发送一个固定字符串 have connected to you! 。那么设想一下,接收端接收到的数据是咋样的?
是否每一次接受,收到的都是一段 have connected to you! 似乎,应该是吧??

答案是否定的!!! 下面是输出的结果
本次接受:have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!
本次接受:have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!
本次接受:have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!
本次接受:have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you!have connected to you
- 思考为什么一次接受,会有这么多的have connected to you! ?
- 这会对程序造成什么影响?
- 如何解决这种问题?
上面3个问题明白了,基本上粘包也就明白了
第一个问题为什么一次接受会有这么多的have connected to you!
我也一度以为接收一次,就是一个have connected to you! 上学那会尽管常常用到Socket 来建立tcp 连接,七层模型和三次握手背的有模有样,但是我确实不知道Tcp粘包。
因为我对传输的要求比较低,常常是过一段时间(比如好几秒钟)才发送一次这样的场景。这种情况下不大会出现粘包。(可以试下再send 下面Sleep(1000))
此时的场景 大概是这样的。 客户端服务Send -----服务端Recv
过一段时间 客户端再 Send ----服务端Recv 如此循环
这样的话,服务端每一次接收,刚好能接收到 上一次客户端发过来的全部数据。
这里我们发送的间隔非常短,每一次Send 其实系统只是把要发送的数据拷贝到发送缓冲区,系统处理发送缓冲区时可能会把我们的多次发送,合并为一次发送 。即Send(1),Send(2),Send(3) 最终一次发送Send(123).
而接收端就直接一次就接收到了 Recv(123) .
第二个问题这会对程序造成什么影响?
服务端该如何解析这个123那?是算一次指令,内容是123 ? 还是算两次指令,第一次是12,第二次是3?
事实上服务端无法判断接受到数据据该解析为 1-2-3 还是 12-3 还是 1-23 还是123.
如果你正在打某网络游戏,某秒钟你产生了20次操作指令到服务端。按目前的情况,服务端是无法正确还原出这20次指令的具体的内容的
第三个问题3如何解决 。
下面拷贝了一块他人博客总结的解决方案
- 发送定长包。如果每个消息的大小都是一样的,那么在接收对等方只要累计接收数据,直到数据等于一个定长的数值就将它作为一个消息。
- 包尾加上\r\n标记。FTP协议正是这么做的。但问题在于如果数据正文中也含有\r\n,则会误判为消息的边界。
- 包头加上包体长度。包头是定长的4个字节,说明了包体的长度。接收对等方先接收包体长度,依据包体长度来接收包体。
- 使用更加复杂的应用层协议。
来实践一下 2,搞明白了2以后,3,4其实也是类似的 。
对发送端来说,改动是很小的。服务端则需要做一些调整 。先约定每次发送,包尾加上 @#$%^& 作为结束

执行结果如下。

可以看到,只要给每次发送的消息加上一个约定的尾巴。接收端就可以根据这个尾巴,把每次发送的消息给分解出来!!
UDP有没有这个问题那?
因为UDP不是面向流的,每一次都有单独的数据报。表现在代码中就是 。Send10次,必须Recv10次,才能把数据读完(不严谨,应该是大于等于10次,但便于理解是这个意思)。
简单点可以理解为,UDP的每一次发送的数据,都是单独的,不会和上一次发送的数据连在一起。
UDP我就不写代码验证了。有兴趣可以自己试试看。
下次再讨论一下SOCKET 的IO模型把
Socket编程 Tcp和粘包的更多相关文章
- socket基于TCP(粘包现象和处理)
目录 6socket套接字 7基于TCP协议的socket简单的网络通信 AF_UNIX AF_INET(应用最广泛的一个) 报错类型 单一 链接+循环通信 远程命令 9.tcp 实例:远程执行命令 ...
- C/C++ socket编程教程之九:TCP的粘包问题以及数据的无边界性
C/C++ socket编程教程之九:TCP的粘包问题以及数据的无边界性 上节我们讲到了socket缓冲区和数据的传递过程,可以看到数据的接收和发送是无关的,read()/recv() 函数不管数据发 ...
- TCP通信粘包问题分析和解决
转载至https://www.cnblogs.com/kex1n/p/6502002.html 在socket网络程序中,TCP和UDP分别是面向连接和非面向连接的.因此TCP的socket编程,收发 ...
- TCP通信粘包问题分析和解决(全)(转)
TCP通信粘包问题分析和解决(全) 在socket网络程序中,TCP和UDP分别是面向连接和非面向连接的.因此TCP的socket编程,收发两端(客户端和服务器端)都要有成对的socket,因此,发送 ...
- TCP拆包粘包之分隔符解码器
TCP以流的方式进行数据传输,上层的应用协议为了对消息进行区分,往往采用如下4种方式. (1)消息长度固定,累计读取到长度总和为定长LEN的报文后,就认为读取到了一个完整的消息:将计数器置位,重新开始 ...
- python 网络编程之TCP传输&粘包传输
只有TCP有粘包现象,UDP永远不会粘包. 所谓粘包问题主要还是C/S两端数据传输时 因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的 根本原因:粘包是由TCP协议本身造成的,T ...
- python 全栈开发,Day35(TCP协议 粘包现象 和解决方案)
一.TCP协议 粘包现象 和解决方案 黏包现象让我们基于tcp先制作一个远程执行命令的程序(命令ls -l ; lllllll ; pwd)执行远程命令的模块 需要用到模块subprocess sub ...
- TCP协议粘包问题详解
TCP协议粘包问题详解 前言 在本章节中,我们将探讨TCP协议基于流式传输的最大一个问题,即粘包问题.本章主要介绍TCP粘包的原理与其三种解决粘包的方案.并且还会介绍为什么UDP协议不会产生粘包. 基 ...
- TCP的粘包现象
看面经时,看到有面试官问TCP的粘包问题.想起来研一做购物车处理数据更新时遇到粘包问题,就总结一下吧. 1 什么是粘包现象 TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看, ...
随机推荐
- [刘阳Java]_大型电商网站架构技术演化历程
今年的双十一已经过去一段,作为技术小咖啡,我们先说一下大型电商网站的特点:高并发,大流量,高可用,海量数据.下面就说说大型网站的架构演化过程,它的技术架构是如何一步步的演化的 1. 早期的网站架构 初 ...
- 【LeetCode】12. 整数转罗马数字
12. 整数转罗马数字 知识点:字符串 题目描述 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M. 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 100 ...
- 【动画消消乐】HTML+CSS 自定义加载动画 064(currentColor的妙用!)
前言 Hello!小伙伴! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出- 自我介绍ଘ(੭ˊᵕˋ)੭ 昵称:海轰 标签:程序猿|C++选手|学生 简介:因C语言结识编程,随后转入计算机专 ...
- Python (paramiko) 连接Linux服务器
目录 参考资料 Paramiko 安装 连接Linux 文件上传/下载 文件封装 其他 参考资料 https://www.liujiangblog.com/blog/15/ https://blog. ...
- JAVA基础(代码)练习题61~90
JAVA基础 61.设计一个方法打印数组{'a','r','g','s','e','r'}中下标为1和3的的元素 package Homework_90; /** * 设计一个方法打印数组{'a',' ...
- MySQL问题定位-性能优化之我见
前言 首先任何一个数据库不是独立存在的,也不是凭空想象决定出来的. 数据库的架构离不开应用的场景.所以,为了解决某些深入的问题,首先你得掌握数据库的原理与架构.原理掌握得越深入,越能帮助你定位复杂与隐 ...
- 第十一篇 -- 如何实现MFC窗口的最大化以及控件随最大化
这一篇介绍的是怎么实现MFC窗口的最大最小化,以及里面控件大小也随之改变 第一步:实现窗口最大最小化 首先右击窗口空白处,打开properties,将里面的MaximizeBox和MinimizeBo ...
- python3中的缺省参数和global
关于py中缺省参数: 在声明函数的时候对某些参数(一个或多个)进行赋值,在你调用的时候无需在实参列表中体现该参数,但是在执行的时候会默认加上这个已经在形参中定义好的参数. 但是,缺省参数必须放在最后, ...
- jsp-->js-->jsp之间的关系
jsp和js通过form.submit();发送request请求createdIdSave.jsp 在CreatedIdSave.jsp中进行BL的增删改查操作,在jsp中将值保存到页面的scrip ...
- post传参params与body的区别(@RequestParam和@RequestBody的区别)
1.axios post请求 Content-Type默认为 application/x-www-form-urlencoded,我们传递参数的时,params里面的参数(简单的对象,通过 &quo ...