大多数程序员都要接触网络编程,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. PYTHON startswith (endswith类似)

    Python startswith()方法Python startswith() 方法用于检查字符串是否是以指定子字符串开头,如果是则返回 True,否则返回 False.如果参数 beg 和 end ...

  2. C语言:延时1秒

    使用sleep()函数将程序阻塞,头文件在windows系统和linux系统下是不一样的windowsSleep()//第一个字母大写#include <windows.h>函数原型voi ...

  3. Java中的基本数据类型和引用数据类型的区别

    一.数据类型 Java中的数据类型分为两大类,基本数据类型和引用数据类型. 1.基本数据类型 基本数据类型只有8种,可按照如下分类 ①整数类型:long.int.short.byte ②浮点类型:fl ...

  4. .net core工具组件系列之Redis—— 第一篇:Windows环境配置Redis(5.x以上版本)以及部署为Windows服务

    Cygwin工具编译Redis Redis6.x版本是未编译版本(官方很调皮,所以没办法,咱只好帮他们编译一下了),所以咱们先下载一个Cygwin,用它来对Redis进行编译. Cygwin下载地址: ...

  5. 7.27考试总结(NOIP模拟25)[random·string·queue]

    死亡的尽头,没有神 T1 random 解题思路 这波是找规律完胜了.. lby dalao根据样例找出了正确的式子:\(\dfrac{n^2-1}{9}\) 然而,我这个菜鸡却推出了这样一个错误的式 ...

  6. c语言学习篇二【基础语法】

    一.定义常量: 使用 #define 预处理器. 使用 const 关键字. #include <stdio.h> int main() { const int LENGTH = 10;/ ...

  7. PHP-FPM 远程代码执行漏洞(CVE-2019-11043)

    影响范围 在 Nginx + PHP-FPM 环境下,当启用了上述 Nginx 配置后,以下 PHP 版本受本次漏洞影响,另外,PHP 5.6版本也受此漏洞影响,但目前只能 Crash,不可以远程代码 ...

  8. IOS自动化测试环境搭建(Python & Java)

         一.前言 IOS的App自动化测试与Android的一样,也可以用appium来进行.但是IOS自动化依赖苹果的osx系统.Xcode构建等,且封闭的系统需要苹果开发者账号才可以驱动真机.A ...

  9. vsftpd安装配置

    vsftpd安装配置 vsftpd测试服务器: 192.168.1.191 1.安装: yum provides */vsftpd yum install vsftpd -y 2.匿名用户最基本配置( ...

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

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