大多数程序员都要接触网络编程,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

  1. 思考为什么一次接受,会有这么多的have connected to you!          ?
  2. 这会对程序造成什么影响?
  3. 如何解决这种问题?

上面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如何解决 。

  下面拷贝了一块他人博客总结的解决方案

  1. 发送定长包。如果每个消息的大小都是一样的,那么在接收对等方只要累计接收数据,直到数据等于一个定长的数值就将它作为一个消息。
  2. 包尾加上\r\n标记。FTP协议正是这么做的。但问题在于如果数据正文中也含有\r\n,则会误判为消息的边界。
  3. 包头加上包体长度。包头是定长的4个字节,说明了包体的长度。接收对等方先接收包体长度,依据包体长度来接收包体。
  4. 使用更加复杂的应用层协议。

来实践一下 2,搞明白了2以后,3,4其实也是类似的 。

对发送端来说,改动是很小的。服务端则需要做一些调整 。先约定每次发送,包尾加上 @#$%^&  作为结束

执行结果如下。

可以看到,只要给每次发送的消息加上一个约定的尾巴。接收端就可以根据这个尾巴,把每次发送的消息给分解出来!!

UDP有没有这个问题那?

因为UDP不是面向流的,每一次都有单独的数据报。表现在代码中就是 。Send10次,必须Recv10次,才能把数据读完(不严谨,应该是大于等于10次,但便于理解是这个意思)。

简单点可以理解为,UDP的每一次发送的数据,都是单独的,不会和上一次发送的数据连在一起。

UDP我就不写代码验证了。有兴趣可以自己试试看。

下次再讨论一下SOCKET 的IO模型把


												

Socket编程 Tcp和粘包的更多相关文章

  1. socket基于TCP(粘包现象和处理)

    目录 6socket套接字 7基于TCP协议的socket简单的网络通信 AF_UNIX AF_INET(应用最广泛的一个) 报错类型 单一 链接+循环通信 远程命令 9.tcp 实例:远程执行命令 ...

  2. C/C++ socket编程教程之九:TCP的粘包问题以及数据的无边界性

    C/C++ socket编程教程之九:TCP的粘包问题以及数据的无边界性 上节我们讲到了socket缓冲区和数据的传递过程,可以看到数据的接收和发送是无关的,read()/recv() 函数不管数据发 ...

  3. TCP通信粘包问题分析和解决

    转载至https://www.cnblogs.com/kex1n/p/6502002.html 在socket网络程序中,TCP和UDP分别是面向连接和非面向连接的.因此TCP的socket编程,收发 ...

  4. TCP通信粘包问题分析和解决(全)(转)

    TCP通信粘包问题分析和解决(全) 在socket网络程序中,TCP和UDP分别是面向连接和非面向连接的.因此TCP的socket编程,收发两端(客户端和服务器端)都要有成对的socket,因此,发送 ...

  5. TCP拆包粘包之分隔符解码器

    TCP以流的方式进行数据传输,上层的应用协议为了对消息进行区分,往往采用如下4种方式. (1)消息长度固定,累计读取到长度总和为定长LEN的报文后,就认为读取到了一个完整的消息:将计数器置位,重新开始 ...

  6. python 网络编程之TCP传输&粘包传输

    只有TCP有粘包现象,UDP永远不会粘包. 所谓粘包问题主要还是C/S两端数据传输时 因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的 根本原因:粘包是由TCP协议本身造成的,T ...

  7. python 全栈开发,Day35(TCP协议 粘包现象 和解决方案)

    一.TCP协议 粘包现象 和解决方案 黏包现象让我们基于tcp先制作一个远程执行命令的程序(命令ls -l ; lllllll ; pwd)执行远程命令的模块 需要用到模块subprocess sub ...

  8. TCP协议粘包问题详解

    TCP协议粘包问题详解 前言 在本章节中,我们将探讨TCP协议基于流式传输的最大一个问题,即粘包问题.本章主要介绍TCP粘包的原理与其三种解决粘包的方案.并且还会介绍为什么UDP协议不会产生粘包. 基 ...

  9. TCP的粘包现象

    看面经时,看到有面试官问TCP的粘包问题.想起来研一做购物车处理数据更新时遇到粘包问题,就总结一下吧. 1 什么是粘包现象 TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看, ...

随机推荐

  1. SpringBoot | 3.1 配置数据源

    目录 前言 1. 数据源的自动配置 2. *数据源自动配置源码分析 2.1 DataSourceAutoConfiguration:数据源自动配置类 2.2 JdbcTemplateAutoConfi ...

  2. 看懂UML类图笔记

    在学习设计模式的时候,经常会遇到UML类图,所以就找了一些资料,做一些笔记. 从一个示例开始 下面这个类图,类之间的关系是我们需要关注的: 车的类图结构为<<abstract>> ...

  3. YsoSerial 工具常用Payload分析之CC3(二)

    这是CC链分析的第二篇文章,我想按着common-collections的版本顺序来介绍,所以顺序为 cc1.3.5.6.7(common-collections 3.1),cc2.4(common- ...

  4. node fs-extra文件操作模块的使用(支持同步、异步)

    用法参见:fs-extra

  5. [考试总结]noip模拟20

    第五场,再挂分就没了.. 然后就没了.. 考场上一直想方法. 似乎想到了 \(T1\) 正解. 然而几个 \(k\) 的调试信息都让我迷失了自我. 然后有几句啥都没用的语句加在了上面.. 挂分... ...

  6. python安装pyeda库--windows版

    本页介绍了如何购买自己的PyEDA闪亮副本.PyEDA项目的主要目标是成为主流的Python软件包,并遵守社区中遵守的大多数约定. 支持平台 PyEDA支持Windows以及任何带有C编译器的平台.作 ...

  7. xmind2020 zen 10.3.1安装破解教程

    hi大家好,xmind zen 2020 10.3.1是一款优秀的思维导图工具,我和我爸爸都在用,功能包括去掉xmind zen水印.上传图片等功能,支持windows操作系统! 文章教大家安装并解锁 ...

  8. SQL之case when then用法_之二

    select CustomerNo, Name, Sex, Birthday, IDType, IDNo, validityday, case (null ) when '1' then '高级VIP ...

  9. GE ifix 5.5中关于历史报警表的制作

    在关于污水处理厂项目实施过程中,按照业主要求,需要用到报警历史的查询功能,遂搜资料,整理在ifix5.5下如何实现报警历史的查询,经过一天的研究,以及多天的入坑,出坑,总算完成.现整理如下,供后来人参 ...

  10. zabbix latest.php SQL注入漏洞(CVE-2016-10134)

    Zabbix 2.2.14之前的版本和3.0.4之前的3.0版本 latest.php页面提取cookie中的zbx_sessionid的后16位 246c58ba963457ef http://19 ...