解决Socket粘包问题——C#代码

  前天晚上,曾经的一个同事问我socket发送消息如果太频繁接收方就会有消息重叠,因为当时在外面,没有多加思考 第一反应还以为是多线程导致的数据不同步导致的,让他加个线程锁搞定。后来回到家慢慢思考感觉这个和加锁没啥关系,如果是多线程导致的,消息只会被覆盖呀。后来就上网搜索socket 消息重叠,后来了解到这属于socket粘包。

简单以自己的理解介绍下Socket粘包。

  Socket粘包简单说就是:Socket发送方 发送消息很频繁导致接收方接收到的消息是之前的两个或者多个消息连在一起。至于详细介绍可以百度相关资料了解。

Socket粘包一般分为两种:

1、Socket发送方:Socket发送消息时会将消息存放在一个缓冲区里,等待缓冲区满或者等待时间已到则发送出去。

2、Socket接收方:接收方一般是因为没有及时从Socket缓冲区里取数据导致后来数据累加到一起才获取导致。

在此只介绍发送方导致的

发送方处理方法一般是两种

1、NoDelay=true,NoDelay是否正在使用 Nagle 算法,这是socket提供的一个方法,我试了单独使用感觉效果不大,还有就是在发送后加延时,这样就不会造成粘包。

2、分包方法 即发送消息的头4个字节加上消息长度,接受方接收到数据后先解析长度然后根据消息长度来获取消息。每次接收数据有个总长度 在总长度里循环遍历消息即可。

直接上代码。

分包方法发送端主要代码

            //测试要发送的消息
string[] sendData = new string[] { "", "", "", "", "", "我爱中国 中国爱我 哈哈哈 中国", "大中华你china"};
int userKey = listConnect.SelectedIndex;
if (userKey < )
{
MessageBox.Show("请选择要发送者!");
} else
{
//为了测试循环发送消息
for (int i = ; i < ; i++)
{ //获取消息内容
byte[] msg = Encoding.UTF8.GetBytes(sendData[i]); byte[] array = new byte[msg.Length + + ]; //第一个字节代表 消息类型 1:文字消息 2:文件
array[] = ;
//将消息长度写入4个字节 从第二个2个字节开始写入
ConvertIntToByteArray(msg.Length, ref array); //字节拷贝
Buffer.BlockCopy(msg, , array, , msg.Length);
//socket发送 dic存储的当前连接的socket列表
dic[userKey].Send(array); }
}

接收端消息部分代码

                //循环监听接收消息
while (flag)
{
byte[] bytes = new byte[ * * ]; //消息总长度
int dataLength = ;
dataLength = ServerSocket.receive(out bytes); //判断消息类型
if (bytes[] == )
{ //解决粘包问题代码 int msgBeginIndex = -;
int msgEndIndex = -;
int msgLength = ;
int n = ; /**以下是接收数据包在byte[]中的内容
*
0=1 代表消息类型
1=2 消息长度(消息长度占4个字节)
2=0 ..
3=0 ..
4=0 ..
5=48 消息内容
6=48 ..
以下内容和前面结构一样,粘包导致两个消息粘在一起
7=1
8=2
9=0
10=0
11=0
12=49
13=49
...
******/
while (n < dataLength)
{
//将消息长度4个字节单独提取
byte[] msgLengthByte = new byte[]; for (int i = ; i < ; i++)
{
//msgEndIndex:消息结束所在索引
//第一个次消息长度可能是2;
//第二个长度可能是8了索引这里要使用msgEndIndex;
//最后+2+i:每个消息记录的长度都是从本次消息的第二个字节开始 直到第四个字节 //之所以msgEndIndex默认=-1 消息长度所在位置在前一个消息结束后的第二个字节开始 ;
//-1+2=1 这样保证获取第一个消息所在长度,也能保证后面的消息长度所在位置
msgLengthByte[i] = bytes[msgEndIndex + + i];
}
//将消息长度转成int
msgLength = BitConverter.ToInt32(msgLengthByte, ); //消息开始索引=消息结束索引+6(前面5个字节不是消息内容消息内容都是从第6个字节开始;+6是因为msgEndIndex索引是从-1开始)
msgBeginIndex = msgEndIndex + ; //消息结束索引位置=游标索引开始位置 +消息长度-1 因为消息开始索引本身就是消息开始 索引消息结束必须减除开始索引
msgEndIndex = msgBeginIndex + msgLength - ; //获取消息内容
string receive = Encoding.UTF8.GetString(bytes, msgBeginIndex, msgLength);
if (receive != null)
{
txtLog.BeginInvoke(new Action(() =>
{ txtLog.AppendText(DateTime.Now.ToString("HH:mm:ss") + " " + receive + " \r\n");
}));
} n = msgEndIndex + ;
}
} //文件接收
else if (bytes[] == )
{
}
}

解决Socket粘包问题——C#代码的更多相关文章

  1. C#下利用封包、拆包原理解决Socket粘包、半包问题(新手篇)

    介于网络上充斥着大量的含糊其辞的Socket初级教程,扰乱着新手的学习方向,我来扼要的教一下新手应该怎么合理的处理Socket这个玩意儿. 一般来说,教你C#下Socket编程的老师,很少会教你如何解 ...

  2. 解决socket粘包的两种low版模式 os.popen()和struct模块

    os.popen()模式 server端 import socket import os phone = socket.socket() # 实例化一个socket对象 phone.bind((&qu ...

  3. 网络编程基础【day09】:解决socket粘包之大数据(七)

    本节内容 概述 linux下运行效果 sleep解决粘包 服务端插入交互解决粘包问题 一.概述 刚刚我们在window的操作系统上,很完美的解决了,大数据量的数据传输出现的问题,但是在Linux环境下 ...

  4. Python socket粘包解决

    socket粘包: socket 交互send时,连续处理多个send时会出现粘包,soket会把两条send作为一条send强制发送,会粘在一起. send发送会根据recv定义的数值发送一个固定的 ...

  5. socket粘包现象加解决办法

    socket粘包现象分析与解决方案 简单远程执行命令程序开发(内容回顾) res = subprocess.Popen(cmd.decode('utf-8'),shell=True,stderr=su ...

  6. Netty使用LineBasedFrameDecoder解决TCP粘包/拆包

    TCP粘包/拆包 TCP是个”流”协议,所谓流,就是没有界限的一串数据.TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被TC ...

  7. 百万年薪python之路 -- socket粘包问题解决

    socket粘包问题解决 1. 高大上版解决粘包方式(自定制包头) 整体的流程解释 整个流程的大致解释: 我们可以把报头做成字典,字典里包含将要发送的真实数据的描述信息(大小啊之类的),然后json序 ...

  8. Socket粘包问题的3种解决方案,最后一种最完美!

    在 Java 语言中,传统的 Socket 编程分为两种实现方式,这两种实现方式也对应着两种不同的传输层协议:TCP 协议和 UDP 协议,但作为互联网中最常用的传输层协议 TCP,在使用时却会导致粘 ...

  9. Socket粘包问题终极解决方案—Netty版(2W字)!

    上一篇我们讲了<Socket粘包问题的3种解决方案>,但没想到评论区竟然炸了.介于大家的热情讨论,以及不同的反馈意见,本文就来做一个扩展和延伸,试图找到问题的最优解,以及消息通讯的最优解决 ...

随机推荐

  1. layui框架部分功能介绍

    注意:代码的所有功能都没有导入layui的css样式 一,分页功能 layui框架分页使用,其实layui分页非常简单只需要传入一个总页数就可以很好运用这个功能 下面就看一下我对layui框架分页的介 ...

  2. Longest Substring Without Repeating Characters2015年6月9日

    Given a string, find the length of the longest substring without repeating characters. For example, ...

  3. CAP原理、一致性模型、BASE理论和ACID特性

    CAP原理 在理论计算机科学中,CAP定理(CAP theorem),又被称作布鲁尔定理(Brewer's theorem),它指出对于一个分布式计算系统来说,不可能同时满足以下三点: 一致性(Con ...

  4. 搞定python多线程和多进程

    1 概念梳理: 1.1 线程 1.1.1 什么是线程 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发 ...

  5. 特朗普退出《巴黎协定》:python词云图舆情分析

    1 前言 2017年6月1日,美国特朗普总统正式宣布美国退出<巴黎协定>.宣布退出<巴黎协定>后,特朗普似乎成了“全球公敌”. 特斯拉总裁马斯克宣布退出总统顾问团队 迪士尼董事 ...

  6. 翻译Algorithms Unlocked

    写在前面 本书是由<算法导论>(Introduction to Algorithms)的作者之一Thomas H. Cormen编写的适合对算法感兴趣但自身基础又不好的同学阅读.很多人评价 ...

  7. 小K的H5之旅-HTML的基本结构与基本标签

    一.什么是HTML HTML是超文本标签语言,即网页的源码.而浏览器就是翻译解释HTML源码的工具. 二.HTML文档的结构 HTML文档主要包括三大部分:文档声明部分.<head>头部部 ...

  8. 【初码干货】记一次分布式B站爬虫任务系统的完整设计和实施

    [初码文章推荐] 程序员的自我修养 Azure系列文章 阿里云系列文章 爬虫系列文章 [初码产品推荐] AlphaMS开发模式 闪送达城市中央厨房 今天带来一个有意思的东西-分布式B站爬虫任务系统 这 ...

  9. Java之反射代码演示说明

    还不存在的类–即我们需要使用反射来使用的类 Person类: package com.qf.demo4; public class Person { private String name; publ ...

  10. Java IO流之打印流与标准流

    一.打印流 1.1打印流特点与构造方法 1)PrintStream和PrintWriter类都提供了一系列重载的print和println方法来输出各种类型的数据. 2)PrintStream和Pri ...