Linux网络编程TCP粘包问题解析及解决方法

news2024/11/14 13:34:47

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、一次发送多个数据实验
  • 二、导致问题的原因
  • 三、解决方案之一:延时发送
  • 四、知识点补充发送缓冲区和接收缓冲区
  • 五、解决方法
  • 总结


前言

本篇文章将引入一个重要的知识:TCP的粘包问题,在发送数据的时候可能会出现粘包的问题,很多初学者应该都不知道什么是粘包,那么本篇文章将讲解什么是粘包,又怎么样解决粘包,这将是一个重点问题,希望大家好好理解。
下面我们先做一个小实验。

一、一次发送多个数据实验

改写之前编写的client程序:

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <strings.h>
#include <arpa/inet.h>
#include <string.h>

int main(int argc, char **argv)
{
    int sockfd = 0;
    int n = 0;
    char* send_buf;
    struct sockaddr_in servaddr;

    if(argc != 2)
    {
        printf("parameter is err\n");
    }

    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf(" socket is err\n ");
    }

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(8888);

    if(inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
    {
        printf("inet_pton is err\n");
    }

    if(connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
    {
        printf("connect is err\n");
    }

    send(sockfd, "Hello", 5, 0);
    send(sockfd, "World", 5, 0);
    send(sockfd, "Client", 6, 0);

    // while (1)
    // {
    //     printf("input :\n");

    //     scanf("%s", send_buf);

    //     send(sockfd, send_buf, strlen(send_buf) + 1, 0); 

    //     printf("\n");
    // }

    if(n < 0)
    {
        printf("read err\n");
    }

    close(sockfd);

    return 0;    

}

这里使用send函数连续发送三个字符串给服务端,正常我们认为输出的结果应该是:
Hello
World
Client
因为我们是分开三次发送的,但是结果却不是这样的。
运行服务端输出结果如下:
在这里插入图片描述
输出的结果是这三个字符串都连在一起了,这就是我们说的粘包问题,当一次性发送多个字符串时就会发生这样的问题。

二、导致问题的原因

在网络传输中,TCP 协议传输的是数据流,而非数据包。因此,服务端不知道发送方发送的消息的具体边界。因为在数据发送过程中,TCP 会对较小的数据包进行合并,从而减少发送频率和网络流量,这就可能导致数据在接收方处出现黏包的情况。

三、解决方案之一:延时发送

每次发送过后都延时一段时间,这样处理服务端可以接收到我们想要的结果。
但是这样的处理有一个很明显的缺点就是大量使用了延时函数,这样处理会降低程序的效率。所以这个处理方法是不太可行的。
那么为什么使用延时函数后服务端可以打印出我们想要的结果呢?
使用了延时函数这样能够使数据缓冲区有时间将数据发送给接收方并进行处理,避免了第二条或第三条消息被阻塞或黏包的情况。

send(sockfd, "Hello", 5, 0);
sleep(1);
send(sockfd, "World", 5, 0);
sleep(1);
send(sockfd, "Client", 6, 0);
sleep(1);

四、知识点补充发送缓冲区和接收缓冲区

初学者会有一个很大的误区。会认为客户端和服务端之前的数据传递是直接的,其实这是不正确的,他们之间的数据传递需要通过缓冲区来实现。
在这里插入图片描述
发送缓冲区是一个缓存区,它存放着客户端或服务端将要发送的数据。

接收缓冲区用来存放接收到的数据,接收端从接收缓冲区中取出数据,并将它们合并成完整的数据,再提供给上层应用程序使用。

当发送数据时数据会先发送到发送缓冲区中,接收数据时也需要从接收缓冲区中接收数据。并不是直接发送数据到对端的。

在网络通信中,发送方应用程序把要发送的数据存储在发送缓冲区中,操作系统会负责将缓冲区中的数据封装成网络数据包,并通过网络将数据包发送给接收方。

这就是为什么连续发送三次数据读取出来的时候数据是粘连在一起的原因了。发送数据的速度是非常快的,发送的数据都会保存在发送缓冲区当中,操作系统不知道这是发送的三次数据,他只负责运输数据,所以他将这三次的数据当成一次数据全部发送过去了。

使用了延时函数后操作系统有足够时间处理一次数据的接收和发送,所以这样不会出现粘包问题。

五、解决方法

使用自定义的协议,规定好数据包的格式和数据长度,以及数据包之间的分隔符,从而在接收端可以正确解析数据包,避免数据粘包等问题。

解决这个问题可以使用指定通信协议的方法来解决,规定数据的首部尾部等,这样对端根据制定的通信协议就能够知道是发送了几次数据了,并将正确的所需要的数据解析出来。

总结

本篇文章是非常重要的,希望大家好好吸收和消化,理解TCP发送数据的工程中为什么会出现粘包问题。
后续的文章将会讲解如何指定通信协议。

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

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

相关文章

Java-JDK动态代理(AOP)使用及实现原理分析

Java-JDK动态代理&#xff08;AOP&#xff09;使用及实现原理分析 第一章:代理的介绍 介绍:我们需要掌握的程度 动态代理(理解) 基于反射机制 掌握的程度: 1.什么是动态代理? 2.动态代理能够做什么? 后面我们在用Spirng和Mybatis的时候,要理解怎么使用的. 1.什么是代理? 代理…

PID循迹机器人及整定

如何对线路循迹机器人进行编程 如何对线路循迹机器人进行编程 (robotresearchlab.com)PID调谐文章&#xff1a;http://robotresearchlab.com/2019/02/16/pid-line-follower-tuning/ 介绍人们选择对循迹机器人进行线路编程的两种主要方式&#xff0c;并比较两者。将详细比较“…

绘声绘影2023简体中文版新功能介绍

会声会影是一款专业的数字音频工作站软件,它提供强大的音频编辑和制作功能,被广泛应用于音乐创作、录音棚录制以及现场演出等领域。会声会影的最新版本会声会影2023将于2022年底发布,主要功能和新功能详述如下: 会声会影2023主要功能: 1. 直观易用的界面:会声会影采用简洁而不…

C语言入门篇——数组篇

目录 1、数组 2、一维数组的创建和初始化 2.1数组的创建方式&#xff1a; 2.2数组的初始化 2.3一维数组的使用 ​2.4一维数组在内存中的存储 3、二维数组的创建和初始化 3.1二维数组的创建 3.2二维数组的初始化 3.3二维数组的使用 3.4二维数组在内存中的存储 4、数组…

SpringBoot中一个注解优雅实现重试Retry框架

目录: 1、简介2、实现步骤 1、简介 重试&#xff0c;在项目需求中是非常常见的&#xff0c;例如遇到网络波动等&#xff0c;要求某个接口或者是方法可以最多/最少调用几次&#xff1b;实现重试机制&#xff0c;非得用Retry这个重试框架吗&#xff1f;那肯定不是&#xff0c;相信…

【云计算•云原生】2.云计算环境下的新趋势—云原生

文章目录 1.什么是云原生2.云原生概述2.1 微服务2.2 容器云2.3 serverless无服务器2.4 DevOps2.5 持续集成和持续交付2.6 openStack 1.什么是云原生 按照自己的理解&#xff0c;可以将云原生拆分成云原生&#xff0c;云就是上一节中的云计算的云&#xff1b;原生即为诞生的环境…

Visual Studio C# WinForm开发入门(3):各种控件介绍

1、窗体 窗口就是打开程序我们所面对的一个面板&#xff0c;里面可以添加各种控件&#xff0c;如下图所示&#xff0c;我们可以在属性栏设置其标题名称、图标、大小等。 双击标题框&#xff0c;会生成Load函数&#xff0c;也可以到事件里面去找 Load函数是窗口生成后需要…

Spring Doc OpenAPI3.0 抛弃SpringFox拥抱SpringDoc

Spring Doc 1 简介 SpringDoc是SpringBoot 的API文档工具。官网&#xff1a;https://springdoc.org/ 在使用SpringBoot 2.6以前去创建API文档工具一般会采用SpringFox提供的Swagger库&#xff0c;但是由于SpringBoot版本的不断升级和SpringFox摆烂不更新&#xff0c;导致了S…

springboot项目需要读取非application.yml/properties 的配置文件

目录&#xff1a; 1、操作步骤2、总结3、扩展4、第二种方法获取配置文件bean 1、操作步骤 1.新建配置文件&#xff1a; 2.编辑配置文件&#xff1a; test-serverrd-dev02.jr.rong360.com3.新建Config类&#xff1a; Component PropertySource(value "kirara.properti…

销量破亿,董洁直播间凭何出圈?

近期&#xff0c;“没有五位数走不出”的董洁直播间火了…… 纵观这几年各大平台直播带货&#xff0c;火已不是什么新鲜事&#xff0c;而为何董洁的直播能火上热搜呢&#xff1f;本期&#xff0c;千瓜将解析董洁直播&#xff0c;同品牌方聊聊小红书直播的那些事儿。董洁「种草式…

Win10分辨率怎么看?2种必须学会的方法!

案例&#xff1a;win10分辨率 【为了方便办公&#xff0c;最近我的电脑连接了2个显示屏&#xff0c;但感觉电脑显示怪怪的&#xff0c;可能是分辨率设置不对&#xff0c;大家知道应该怎么查看电脑的分辨率吗&#xff1f;感谢感谢&#xff01;】 我们的win10系统支持多种分辨率…

ChatGPT的未来:人工智能技术的新发展趋势

第一章&#xff1a;人工智能技术的新发展趋势 近年来&#xff0c;随着人工智能技术的不断发展和应用&#xff0c;ChatGPT这样的大型自然语言处理模型已经成为人工智能技术的重要组成部分。未来&#xff0c;人工智能技术的发展将更加快速&#xff0c;我们可以看到以下几个方面的…

制造型企业为何需要MES管理系统,企业怎样选择合适的MES

MES管理系统是专门针对制造型企业而设计的&#xff0c;能实现对生产车间、工厂信息化管理&#xff0c;帮助制造型企业提高生产效率&#xff0c;加快数字化转型。目前针对制造型企业生产效率、企业竞争力和生产管理状况的需求&#xff0c;MES管理系统已经成为实现生产经营目标的…

MySQL创建用户并赋权限

MySQL创建用户并赋权限 省流1.创建mysql用户1.1 新建用户1.2 查询用户信息 2. 授权用户2.1 指定数据库和表赋权2.2 赋予全部权限2.3 查看用户权限2.4 回收用户权限 3. 修改用户密码4. 删除用户5. 刷新权限(务必执行) 省流 如果只是希望新建一个用户并且赋予全部执行权限&#…

android react native报错

1.报错图片 解决方案&#xff1a; android下的build.gradle文件 修改 如图 报错 E:/androidData/caches/transforms-2/files-2.1/399126eae79af6235d7a4ae871926a31/jetified-kotlin-stdlib-1.6.10.jar!/META-INF/kotlin-stdlib.kotlin_module: Module was compiled with an i…

华为云 HCIP云迁移 学习课程提供的考试样题提交之后没有反馈正确答案的问题

最近在考HCIP的云迁移&#xff0c;但是他提供的考试样题昨晚发现没有正确答案&#xff0c;只会告诉你对错&#xff0c;判断题还好解决&#xff0c;但是多选题就麻烦了。这边研究了一下&#xff0c;share一下&#xff0c;方便大家学习和验证自己的学习成果 这边去看了他的 api r…

杰理-OTA升级电量限制

杰理-OTA升级电量限制 获取升级异常状态标志位&#xff08;升级过程中断开重新连接&#xff0c;不做电量限制&#xff09;

【观察】华为:运力算力存力“协同”,推动数字生产力“跃升”

可以看到&#xff0c;过去几年数字化转型已经席卷全球&#xff0c;随着新技术的广泛应用&#xff0c;新的机会和价值正在不断被发现和创造。从某种程度上说&#xff0c;数字化转型不再是“可选项”&#xff0c;而变成了“必选项”。 确实如此&#xff0c;目前已经有超过170多个…

基于JS简单甘特图(IT枫斗者)

基于JS简单甘特图 基于JS简单甘特图 先来看一下效果吧&#xff0c;这里的需求是从早上的5点为开始时间&#xff0c;到第二天到凌晨5点 前期准备 其实网上有很多甘特图的实现方式&#xff0c;但是他们都只能具象到天&#xff0c;不能具体到某个时间点&#xff0c;而且每一个…

ESD/EMI防护设计

内容摘取自<Rockchip_RK3568_Hardware_Design_Guide_V1.0_CN.pdf> 1.1概述 本章对于RK3568产品设计中的ESD/EMI防护设计给出了建议&#xff0c;帮助客户更好的提高产品的抗静电、抗电 磁干扰水平。 1.2 术语解释 本章中的术语解释如下&#xff1a;  ESD&#xff08;E…