1、TCP和UDP的区别

  • TCP(transport control protocol,传输控制协议)是面向连接的,面向流的,提供高可靠性服务。收发两端(客户端和服务器端)都要有一一成对的socket,因此,发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包。这样,接收端,就难于分辨出来了,必须提供科学的拆包机制。 即面向流的通信是无消息保护边界的(数据没有界限)
  • UDP(user datagram protocol,用户数据报协议)是无连接的,面向消息的,提供高效率服务。不会使用块的合并优化算法, 由于UDP支持的是一对多的模式,所以接收端的skbuff(套接字缓冲区)采用了链式结构来记录每一个到达的UDP包,在每个UDP包中就有了消息头(消息来源地址,端口等信息),这样,对于接收端来说,就容易进行区分处理了。 即面向消息的通信是有消息保护边界的。


这样就会造成如下三种情况:

1.接收端依次从发送端接收Msg1,Msg2;(正常)

2.Msg1被发送端分割为多段发送给接收端(或者接收端先接收到Msg1和Msg2的部分数据,再接收到msg2剩下的数据);(断/拆包)

3.Msg1和Msg2粘和在一起被发送端一次发送给接收端;(粘包)

PS:因此,通常我们需要将接收的消息通过整理,然后分别合成一个我们需要的数据包,然后才将这个消息发送给接收端。

2、解决TCP断包、粘包的的代码

1. 协议如下

报头

长度

数据段(N个字节)

校验和

0x55AA

len

命令类型(id)

目标地址

主机地址

预留

其它

CRC

2 个字节

2 个字节(从报头到检验和所有长度)

n1个字节

n2个字节

n3个字节

n3个字节

n4个字节

1个字节(从报头到数据完的校验和)。

2.代码如下:

void TcpClient::rcvSlot()
{
  static QByteArray allBa;  //用来存所有文件
  allBa.append(tcpClient->readAll());  //读取数据
  int head = allBa.indexOf(HEAD);    //报文头的位置,HEAD=0x55aa
  uint16_t length = 0;                               //报文(协议中)的长度
  QByteArray currentBa;
  bool checkResult = false;
  while (-1 != head)           //报文头检验
  {
    allBa = allBa.mid(head);      //去掉报头之前的
    memcpy(&length, allBa.data() + 2, 2);
    if (allBa.size() >= length)      //长度够,进行解析。报文长度校验
    {
      currentBa = allBa.mid(0, length); //获取当前完整包
      id = Mymethod:isCRC(currentBa);  //报文的和校验和id校验。(校验通过返回大于0,异常返回-1)
      if ( id)    //通过校验将数据发送
      {
        emit getPacketSignal(id, currentBa);
        qDebug() << "接收指令:" << currentBa.toHex().toUpper();

        allBa.remove(0,length+position);    //通过校验去掉取出的内容和报文头之前的内容
      }

      else

        allBa.remove(0,position+2);    //未通过校验则去掉报文头

    }

    else

      break;

    head = allBa.indexOf(HEAD);   //刷新报文头的位置
  }
}

PS:本人第一次写,若有不足之处请大家多多指出,希望能够和大家一起持续进步!

tcp通信,解决断包、粘包的问题的更多相关文章

  1. UNIX网络编程——tcp流协议产生的粘包问题和解决方案

    我们在前面曾经说过,发送端可以是一K一K地发送数据,而接收端的应用程序可以两K两K地提走数据,当然也有可能一次提走3K或6K数据,或者一次只提走几个字节的数据,也就是说,应用程序所看到的数据是一个整体 ...

  2. Socket 编程中,TCP 流的结束标志与粘包问题

    因为 TCP 本身是无边界的协议,因此它并没有结束标志,也无法分包. socket和文件不一样,从文件中读,读到末尾就到达流的结尾了,所以会返回-1或null,循环结束,但是socket是连接两个主机 ...

  3. [转]java nio解决半包 粘包问题

    java nio解决半包 粘包问题 NIO socket是非阻塞的通讯模式,与IO阻塞式的通讯不同点在于NIO的数据要通过channel放到一个缓存池ByteBuffer中,然后再从这个缓存池中读出数 ...

  4. tcp流协议产生的粘包问题和解决方案

    我们在前面曾经说过,发送端可以是一K一K地发送数据,而接收端的应用程序可以两K两K地提走数据,当然也有可能一次提走3K或6K数据,或者一次只提走几个字节的数据,也就是说,应用程序所看到的数据是一个整体 ...

  5. C#网络编程学习(5)---Tcp连接中出现的粘包、拆包问题

    本文参考于CSDN博客wxy941011 1.疑问 我们使用第四个博客中的项目. 修改客户端为:连接成功后循环向服务器发送从1-100的数字.看看服务器会不会正常的接收100次数据. 可是我们发现服务 ...

  6. Python 32 通信循环 连接循环 粘包问题

    一:通信循环 二:连接循环 三:粘包问题

  7. Go语言网络通信---tcp上传大文件(粘包问题还需优雅解决)

    server端: package main import ( "bufio" "encoding/binary" "fmt" "n ...

  8. tcp协议传输中的粘包问题

    什么是粘包问题 tcp是流体协议. 其nagle算法会将数据量较小. 并且发送间隔时间较短的多个数据包合并为一个发送. 网络传输的时候是一段一段字节流的发送. 在接收方看来根本不知道字节流从何开始. ...

  9. netty10---分包粘包

    客户端:根据 长度+数据 方式发送 package com.server; import java.net.Socket; import java.nio.ByteBuffer; public cla ...

  10. 网络编程3 网络编程之缓冲区&subprocess&粘包&粘包解决方案

    1.sub简单使用 2.粘包现象(1) 3.粘包现象(2) 4.粘包现象解决方案 5.struct学习 6.粘包现象升级版解决方案 7.打印进度条

随机推荐

  1. GitHub不能访问问题

    在C:\Windows\System32\drivers\etc文件夹下HOSTS里面最后添加: 192.30.253.112 github.com 192.30.253.113 github.com ...

  2. Java中JNI的使用详解第六篇:C/C++中的引用类型和Id的缓存

    首先来看一下C/C++中的引用 从Java虚拟机创建的对象传到本地C/C++代码时会产生引用,根据Java的垃圾回收机制,只要有引用存在就不会触发该引用指向的Java对象的垃圾回收 第一.局部引用: ...

  3. BZOJ 3626: [LNOI2014]LCA(树剖+差分+线段树)

    传送门 解题思路 比较有意思的一道题.首先要把求\(\sum\limits_{i=l}^r dep[lca(i,z)]\)这个公式变一下.就是考虑每一个点的贡献,做出贡献的点一定在\(z\)到根节点的 ...

  4. 一次修复MySQL数据库的经历

    一次修复MySQL数据库的经历 实验室服务器的硬盘满了,结果导致一个线上服务的MySQL数据库的两个表坏了.具体症状是desc cdb_searchindex显示 ERROR 1017 (HY000) ...

  5. Python-爬虫-爬取知乎的标题和当页显示的文字

    # coding:utf-8 import requests from bs4 import BeautifulSoup quesNumStr = str(input("请输入搜索关键字:& ...

  6. Openstack Nova 源码分析 — 使用 VCDriver 创建 VMware Instance

    目录 目录 前言 流程图 nova-compute vCenter 前言 在上一篇Openstack Nova 源码分析 - Create instances (nova-conductor阶段)中, ...

  7. LOG2_8BIT, LOG2_16BIT, LOG2_32BIT, LOG64_8BIT, LOG2

    #define LOG2_8BIT(v) (8 - 90/(((v)/4+14)|1) - 2/((v)/2+1)) #define LOG2_16BIT(v) (8*((v)>255) + L ...

  8. Codeforces 1168A Increasing by Modulo

    题目链接:http://codeforces.com/problemset/problem/1168/A 题意:给一个数组,数组中元素范围为0~n,每次你可以选择若干元素进行(ai+1)%m的操作,问 ...

  9. 剑指offer——02二维数组中的查找

    题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数 ...

  10. pyhton2与python3的使用区别

    刚刚开始学习python这门编程语言,考虑到python不同版本的一些用法不同,收集整理了一份python2与python3之间的区别,目前可能不全 编码(核心类) Python2默认编码ascii, ...