C# 使用Pipelines处理Socket数据包

写在前面

在上一篇中对Pipelines进行简单的了解,同时也留下了未解的问题,如何将Pipelines类库运用到Socket通讯过程中来解决粘包和分包。链接地址如下: 初识System.IO.Pipelines icon-default.png?t=N7T8https://rjcql.blog.csdn.net/article/details/135211047

这一篇做了一个完整的demo,使用Pipelines接收和处理来自多个客户端发出的消息;相对于以往在报文包头放包体长度再结合结束符来判断的方式,确实要简洁了许多。

代码实现

服务端实现

using System.Net.Sockets;
using System.Net;
using System.Text;class Program
{static async Task Main(){SocketServerForPiplines();}static async void SocketServerForPiplines(){Console.WriteLine("Socket Server");// 创建服务端Socket对象var serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);serverSocket.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9090));serverSocket.ReceiveTimeout = 1000;serverSocket.SendTimeout = 1000;serverSocket.Listen(1000);Console.WriteLine("服务端启动监听");while (true){var clientSocket = serverSocket.Accept();Console.WriteLine("有客户端连上了");var handler = new PiplinesHandler(clientSocket);await handler.StartReceiveAsync();}Console.ReadLine();}
}

 PiplinesHandler 类:

using System;
using System.Buffers;
using System.Collections.Generic;
using System.IO.Pipelines;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;namespace PipelinesTester
{public class PiplinesHandler{private const int _minimumBufferSize = 512;private Socket _socket;private Pipe _pipe;public PiplinesHandler(Socket socket){_socket = socket;var options = new PipeOptions(pauseWriterThreshold: 4096, resumeWriterThreshold: 1024);_pipe = new Pipe(options);}public async Task StartReceiveAsync(){Task receiveTask = ReceiveMessageAsync();Task processTask = ProcessMessageAsync();await Task.WhenAll(receiveTask, processTask);}private async Task ReceiveMessageAsync(){PipeWriter writer = _pipe.Writer;while (true){try{//从writer申请缓冲区Memory<byte> memory = writer.GetMemory(_minimumBufferSize);//从socket读取数据,直接写入到缓冲区中,即直接写入了PipeWriter中        int bytesRead = await _socket.ReceiveAsync(memory, SocketFlags.None);if (bytesRead == 0){break;}//前移写标志位writer.Advance(bytesRead);//通知Reader,可以读取了var result = await writer.FlushAsync();if (result.IsCompleted)break;}catch (Exception e){Console.WriteLine(e);break;}}await writer.CompleteAsync();try{_socket.Shutdown(SocketShutdown.Both);_socket.Close();}catch (Exception e){Console.WriteLine(e);}}private async Task ProcessMessageAsync(){PipeReader _pipeReader = _pipe.Reader;while (true){//读取消息var result = await _pipeReader.ReadAsync();var buffer = result.Buffer;//查找结束符            SequencePosition? position = buffer.PositionOf((byte)'\n');if (position == null){continue;}// 处理消息var line = buffer.Slice(0, position.Value);string msg = Encoding.UTF8.GetString(line);Console.WriteLine(msg);// 前移PipeReaderbuffer = buffer.Slice(buffer.GetPosition(1, position.Value));_pipeReader.AdvanceTo(buffer.Start, buffer.End);// Stop reading if there's no more data coming.if (result.IsCompleted){break;}}await _pipeReader.CompleteAsync();}}
}

客户端实现

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;class Program
{static void Main(string[] args){TcpClientTest();}static void TcpClientTest(){Console.WriteLine("TcpClient");var msg = $"这是来自客户端的消息{DateTime.Now.ToString("yyyy-MM-dd:HH:mm:ss")}\n";var client = new TcpClient("127.0.0.1", 9090);var sendStream = client.GetStream();var sendBytes = Encoding.Default.GetBytes(msg);sendStream.Write(sendBytes, 0, sendBytes.Length);sendStream.Flush();sendStream.Close();//关闭网络流  client.Close();//关闭客户端  Console.WriteLine(msg);Console.ReadLine();}
}

调用示例

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

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

相关文章

Hive安装笔记——备赛笔记——2024全国职业院校技能大赛“大数据应用开发”赛项——任务2:离线数据处理

将下发的ds_db01.sql数据库文件放置mysql中 12、编写Scala代码&#xff0c;使用Spark将MySQL的ds_db01库中表user_info的全量数据抽取到Hive的ods库中表user_info。字段名称、类型不变&#xff0c;同时添加静态分区&#xff0c;分区字段为etl_date&#xff0c;类型为String&am…

前端开发之通过vue-office组件实现文件预览

前端开发之通过vue-office组件实现文件预览 前言效果图docx文件xlsx文件pdf文件 vue中简单案例1、安装组件2、vue中代码 前言 在实现文件预览的时候我们可以通过vue-office组件来实现文件的预览效果 效果图 docx文件 xlsx文件 pdf文件 vue中简单案例 1、安装组件 整体安装…

RabbitMQ入门指南(九):消费者可靠性

专栏导航 RabbitMQ入门指南 从零开始了解大数据 目录 专栏导航 前言 一、消费者确认机制 二、失败重试机制 三、失败处理策略 四、业务幂等性 1.通过唯一标识符保证操作的幂等性 2.通过业务判断保证操作的幂等性 总结 前言 RabbitMQ是一个高效、可靠的开源消息队列系…

词表示:语言与计算的桥梁

目录 前言1 什么是词表示2 独热表示3 上下文表示4 分布式表示结语 前言 在自然语言处理领域&#xff0c;词语的表示是一个基本挑战。将词语转换为计算机可以理解的符号&#xff0c;衡量词语之间的相似度&#xff0c;捕捉它们之间复杂的关系&#xff0c;是使机器能够理解和处理…

Bluetooth Mesh 入门学习干货,参考Nordic资料(更新中)

蓝牙网状网络&#xff08;Bluetooth mesh&#xff09;概念 概述 蓝牙Mesh Profile | Bluetooth Technology Website规范&#xff08;Mesh v1.1 后改名Mesh ProtocolMesh Protocol | Bluetooth Technology WebsiteMesh Protocol&#xff09;是由蓝牙技术联盟(Bluetooth SIG)开…

EasyExcel实现动态表头(注解实现)

要实现上述动态头&#xff0c;按每日统计&#xff0c;每月统计&#xff0c;每年统计。而时间是一直变化&#xff0c;所以我们需要表头也一直动态生成。 首先&#xff0c;我们需要定义所需要实体类 public class CountDayData {ExcelProperty(value "业务员姓名")p…

css 设置字体渐变色和阴影

一、需求 我们平时写样式的时候可能遇到需要将字体设置成渐变色&#xff0c;这样能使界面整体美化提升&#xff0c;那么css怎么去实现这个功能呢&#xff1f;下面我介绍一种常用的方法&#xff0c;欢迎大家补充 二、渐变实现 先看效果图&#xff1a; 直接上代码&#xff1a; /…

Seem环境安装

创建虚拟环境 conda create -n seem python3.8 conda activate seem 安装相关依赖&#xff1a;&#xff08;不按照的话会报错&#xff09; sudo apt-get install openmpi-bin libopenmpi-devconda install gcc_linux-64pip install mpi4py 导入环境 export PYTHONPATH$(pwd…

开发效率之把握需求、减少返工

前言 当年初入软件开发行业的我&#xff0c;拿到需求就莽&#xff0c;要设计没设计&#xff0c;要分析没分析&#xff0c;结果就是没理清楚需求&#xff0c;致使频频返工。 需求没理解对&#xff0c;做得再多再好也白搭。 估算需求把握程度 假如每个IF分支的“是”加一分&…

2024 年全球顶级的 3 款 桌面 PDF 转换工具

桌面 PDF 转换器工具是一种软件应用程序&#xff0c;使用户能够将 PDF 文件与不同的文件格式相互转换。奇客PDF转换、Nitro Pro 和 Foxit PhantomPDF 是市场上最好的桌面 PDF 转换工具。 在选择最好的 PDF 转换器软件时&#xff0c;需要考虑的一个重要因素是它与其他软件的集成…

nvm 的安装及使用 (Node版本管理器)

目录 1、nvm 介绍 2、nvm安装 3、nvm 使用 4、node官网可以查看node和npm对应版本 5、nvm安装指定版本node 6、安装cli脚手架 1、nvm 介绍 NVM 全称 node.js version management &#xff0c;专门针对 node 版本进行管理的工具&#xff0c;通过它可以安装和切换不同版本的…

数据链路层解读

基本介绍 概述 数据链路层使用的信道主要有两种类型 点对点信道。使用一对一的点对点通信方式的信道。广播信道。使用一对多的广播通信方式的信道。由于广播信道上连接的主机很多&#xff0c;必须使用专用的共享信道协议来协调这些主机的数据发送&#xff0c;因此通信过程比较…

【Windows】共享文件夹拍照还原防火墙设置(入站,出站设置)---图文并茂详细讲解

目录 一 共享文件夹(两种形式) 1.1 普通共享与高级共享区别 1.2 使用 二 拍照还原 2.1 是什么 2.2 使用 三 防火墙设置&#xff08;入栈&#xff0c;出站设置&#xff09; 3.1 引入 3.2 入站出站设置 3.2.1入站出站含义 3.3入站设置 3.4安装jdk 3.5使用tomcat进行访…

sql_lab之sqli中的堆叠型注入(less-38)

堆叠注入&#xff08;less-38&#xff09; 1.判断注入类型 http://127.0.0.3/less-38/?id1 and 12 -- s 没有回显 http://127.0.0.3/less-38/?id1 and 11 -- s 有回显 则说明是单字节’注入 2.查询字段数 http://127.0.0.3/less-38/?id1 order by 4 -- s 报错 http:/…

智能优化算法应用:基于人工兔算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于人工兔算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于人工兔算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.人工兔算法4.实验参数设定5.算法结果6.参考文…

取证工具volatility插件版学习记录

更新时间&#xff1a;2023年12月18日11:48:29 1. 背景描述 在以前学习过volatility的基础功能&#xff0c;主要是使用volatility独立版进行学习的&#xff0c;前几天遇到一个ctf赛事&#xff0c;需要用到的是volatility的mimikatz模块&#xff0c;因为以前没使用过那个模块&…

【Filament】立方体贴图(6张图)

1 前言 本文通过一个立方体贴图的例子&#xff0c;讲解三维纹理贴图&#xff08;子网格贴图&#xff09;的应用&#xff0c;案例中使用 6 张不同的图片给立方体贴图&#xff0c;图片如下。 读者如果对 Filament 不太熟悉&#xff0c;请回顾以下内容。 Filament环境搭建绘制三角…

HTML制作暴雨特效

🎀效果展示 🎀代码展示 <body> <!-- partial:index.partial.html --> <canvas id="canvas-club">

python消费rabbitmq

队列经常用&#xff0c;能保持信息一致性。也能跨语言&#xff0c;java写的生产者&#xff0c;推到队列中&#xff0c;python写的消费者消费。 这里&#xff0c;生成者&#xff0c;我们是java&#xff0c;已经发了一条消息了。 python是使用pika来链接rabbitmq 安装pika pip…

扩展mybatis-plus,保留逻辑删、逻辑查的前提下,扩展硬删除、硬查询

引入相关依赖 <!-- 提示&#xff1a;1. common-mybatis-plus:2100.8.8 中只有4个类文件&#xff0c;是对硬删除、硬查询的扩展支持&#xff0c;如果你不想引入依赖的话&#xff0c;你可以把这四个文件复制到自己的项目中即可2. common-mybatis-plus:2100.8.8 对应mybatis-p…