大多数程序员都要接触网络编程,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. viewport深入理解和使用

    什么是viewport ? viewport是用户网页的可视区域,也可叫做视区.手机浏览器是把页面放在一个虚拟的窗口(viewport)中,通常这个虚拟的窗口比屏幕宽,这样就不用把网页挤到很小的窗口中 ...

  2. 家庭账本开发day10

    系统的增删改查基本功能完成,进行业务流程完整测试.完善相关功能,编写搜索 功能,通过日期,类型等关键字进行搜索,对搜索到的数据表格完成重载 // 监听搜索操作        form.on('subm ...

  3. [源码解析] 深度学习分布式训练框架 horovod (17) --- 弹性训练之容错

    [源码解析] 深度学习分布式训练框架 horovod (17) --- 弹性训练之容错 目录 [源码解析] 深度学习分布式训练框架 horovod (17) --- 弹性训练之容错 0x00 摘要 0 ...

  4. Spark—local模式环境搭建

    Spark--local模式环境搭建 一.Spark运行模式介绍 1.本地模式(loca模式):spark单机运行,一般用户测试和开发使用 2.Standalone模式:构建一个主从结构(Master ...

  5. c语言数据拼包

    单片机数据拼包 对于数据包拼包方式常规方式有: 数组 指针 结构体 流 下文将此三种方式分别列举此数据包的实现. 然后对比优缺点. 本文举例数据包协议: 包头 长度Length 消息类型 消息序列号S ...

  6. Leetcode:面试题 04.04. 检查平衡性

    Leetcode:面试题 04.04. 检查平衡性 Leetcode:面试题 04.04. 检查平衡性 Talk is cheap . Show me the code . /** * Definit ...

  7. 15Java进阶 进程

    1 线程控制 t.join():让主线程进入线程池,等待t执行完才执行. t.sleep():让线程阻塞,休眠一段时间,休眠结束后进入就绪状态.不会释放锁. t.yield():让线程让出CPU,从运 ...

  8. ;~ 小部分AutoHotkey源代码片段测试模板2019年10月9日.ahk

    ;~ 小部分AutoHotkey源代码片段测试模板2019年10月9日.ahk ;~ 此脚本用于测试执行一行或多行AHK脚本源代码的效果;~ 此脚本最后修改于2019年9月22日20时03分;~ 把此 ...

  9. node溢出

    在做项目的过程中,项目越来越大,后面导致项目无法正常启动,查了原因是因为node 溢出了. 先看看溢出时报的错 解决办法:  increase-memory-limit插件 1.在package.js ...

  10. Java数组06——冒泡排序

    冒泡排序 例子:  package array; ​ import java.util.Arrays; ​ public class ArrayDemon08 {     public static ...