基于EasyTcp4Net开发一个功能较为完善的去持久化聊天软件
之前自己写了一篇介绍TCP的一些常用的功能介绍和特征,并且用代码做了示例,最终开发了一个EasyTcp4Net的TCP工具库,其最大的特色就是使用了微软提供的高性能库中的一些数据结构来处理TCP数据。
最近辞职待业在家,也没啥事做,就利用自己写的TCP通讯库基础上开发了一个示例的聊天程序,功能包括,文本发送,图片发送,断线重连,消息发送成功确认,消息发送失败提示等。
示例
发消息给自己

收到消息

发送图片

消息发送中

重连中

发送失败

数据包结构以及拆包
定义数据包结构
数据包结构定义了每次发送一个数据的完整的数据结构,我们将包体长度定义在包头中来解决粘包和断包的问题。
数据包我们采用了简单的序列化成byte数组的方式来发送。
[StructLayout(LayoutKind.Sequential)]
public class Message<TBody> : IMsssage<TBody> where TBody : Packet
{
//数据包包体长度 4字节
public int BodyLength { get; private set; }
//消息类型 4字节
public MessageType MessageType { get; set; }
public TBody? Body { get; set; }
private Message<TBody> Deserialize(byte[] bodyData)
{
var bodyStr = System.Text.Encoding.Default.GetString(bodyData);
Body = JsonSerializer.Deserialize<TBody>(bodyStr);
return this;
}
public static Message<TBody> FromBytes(ReadOnlyMemory<byte> data)
{
Message<TBody> packet = new Message<TBody>();
packet.BodyLength = BinaryPrimitives.ReadInt32BigEndian(data.Slice(0, 4).Span);
packet.MessageType = (MessageType)BinaryPrimitives.ReadInt32BigEndian(data.Slice(4, 4).Span);
packet.Deserialize(data.Slice(8, packet.BodyLength).Span.ToArray());
return packet;
}
public byte[] Serialize()
{
var Length = 4 + 4;
var bodyArray = System.Text.Encoding.Default.GetBytes(JsonSerializer.Serialize(Body));
BodyLength = bodyArray.Length;
Length += bodyArray.Length;
byte[] result = new byte[Length];
result.AddInt32(0, bodyArray.Length);
result.AddInt32(4, (int)MessageType);
Buffer.BlockCopy(bodyArray, 0, result, 8, bodyArray.Length);
return result;
}
public TBody GetBody()
{
return Body;
}
}
public interface IMsssage <out TBody> where TBody : Packet
{
public TBody GetBody();
}
我们在服务端和客户端根据我们定义的数据结构,来调用EasyTcp4Net提供的固定包头来解析数据包
_easyTcpClient.SetReceiveFilter(new FixedHeaderPackageFilter(8, 0, 4, false));
文本/图片发送
我们可以定义消息基类,再拓展两个消息类,一个文本消息,一个图片消息
public class SendMessagePacket : Packet
{
public string MessageId { get; set; } = Guid.NewGuid().ToString();
public string From { get; set; }
public string To { get; set; }
}
图片消息
public class SendImageMessagePacket : SendMessagePacket
{
public byte[] Data { get; set; }
public string FileName { get; set; }
}
文本消息
public class SendTextMessagePacket : SendMessagePacket
{
public string Text { get; set; }
}
我们还需要在界面中增加相关的文本和图片的ViewModel
发送消息的时候,发送者可以立刻将消息添加到聊天界面,然后等待收到自己发送的消息从服务端发来的时候,根据状态判断消息是否发送成功,等待的时候可以将消息设置发送中的界面状态显示,这种发送消息逻辑和微信基本一致。
断线处理
利用EasyTcp4Net提供的断线的事件,可以非常方便的在服务端知道客户端突然断开了,或者在客户端知道和服务端连接断开了。
客户端
_easyTcpClient.OnDisConnected += async (obj, e) =>
{
Title = Title + _disConnectTip;
await ReConnectAsync();
};
主要是触发了重连的机制。
服务端
_easyTcpServer.OnClientConnectionChanged += (obj, e) =>
{
if (e.Status == ConnectsionStatus.DisConnected)
{
_accounts.TryRemove(e.ClientSession.SessionId, out var account);
}
};
主要是将该用户从在线列表中移除。
总结
总体来说做一个聊天软件需要考虑的细节比较多。
示例地址:https://github.com/BruceQiu1996/EasyChat
基于EasyTcp4Net开发一个功能较为完善的去持久化聊天软件的更多相关文章
- 基于SpringBoot开发一个Restful服务,实现增删改查功能
前言 在去年的时候,在各种渠道中略微的了解了SpringBoot,在开发web项目的时候是如何的方便.快捷.但是当时并没有认真的去学习下,毕竟感觉自己在Struts和SpringMVC都用得不太熟练. ...
- 基于线程开发一个FTP服务器
一,项目题目:基于线程开发一个FTP服务器 二,项目要求: 基本要求: 1.用户加密认证 2.允许同时多用户登录 3.每个用户有自己的家目录 ,且只能访问自己的家目录 4.对用户进行磁盘配 ...
- 整合了一个功能强大完善的OA系统源码,php全开源 界面漂亮美观
整合了一个功能强大完善的OA系统源码,php全开源界面漂亮美观.需要的同学联系Q:930948049
- 使用EF+ASP.NET MVC+Bootstrap开发一个功能强大的问卷调查系统
功能简介 支持七大题型 下拉选择题.单选题.多选题.填空题.数字题.问答题.组合/矩阵题(单选组合.多选组合.填空组合.数字组合) 题库支持 每个问卷都要设置姓名.年龄.性别.学历,怎么办?题库帮您轻 ...
- 基于SOUI开发一个简单的小工具
基于DriectUI有很多库,比如 Duilib (免费) soui (免费) DuiVision (免费) 炫彩 (界面库免费,UI设计器付费,不提供源码) skinui (免费使用,但不开放源码, ...
- 【玩转开源】BananaPi R2 —— 第三篇 基于Openwrt开发一个简单的路由器
上一篇讲解了R2的网口配置,这一篇我们以BananaPi R2为例子来实现一个简单的路由器:那么一个简单的路由器应该具备什么样的功能呢?最简单的说就是wan+lan+ap这三个功能. 首先wan+la ...
- 成都开发一个app大概好多钱?
目前,移动APP已成为很多小企业业务销售的新渠道之一,于是问题来了,一般想到要开发一个自己的app,就想问:开发一个app好多钱?去百度.360.搜狗等等平台去找相关的app开发公司咨询或者问问朋友有 ...
- 基于c++11新标准开发一个支持多线程高并发的网络库
背景 新的c++11标准出后,c++语法得到了非常多的扩展,比起以往不论什么时候都要灵活和高效,提高了程序编码的效率,为软件开发者节省了不少的时间. 之前我也写过基于ACE的网络server框架,但A ...
- 基于.NetCore开发博客项目 StarBlog - (13) 加入友情链接功能
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
- 用VSCode开发一个基于asp.net core 2.0/sql server linux(docker)/ng5/bs4的项目(1)
最近使用vscode比较多. 学习了一下如何在mac上使用vscode开发asp.netcore项目. 这里是我写的关于vscode的一篇文章: https://www.cnblogs.com/cgz ...
随机推荐
- linux服务器下安装cbc和ipopt求解器【踩坑总结】
安装CBC求解器 CBC求解器是一个C++库,我们可以通过以下命令在Linux系统中进行安装: sudo apt-get install coinor-cbc 对于Windows操作系统,可以从CBC ...
- C++笔记(13)数组的引用和引用的数组
数组的引用 数组有二个特性,影响作用在数组上的函数:一是不能复制数组,二是使用数组名时, 数组名会自动指向其第一个元素的指针. 因为不能复制,所以无法编写使用数组类型的形参,数组会自动转化为指针.比如 ...
- PB通过OLE方式调用C#.NET DLL时,DLL获取自身根目录
PB通过OLE方式调用C#.NET DLL时, DLL获取自身根目录 System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExe ...
- 别想宰我,怎么查看云厂商是否超卖?详解 cpu steal time
据说有些云厂商会超卖,宿主有 96 个核心,结果卖出去 100 多个 vCPU,如果这些虚机负载都不高,大家相安无事,如果这些虚机同时运行一些高负载的任务,相互之间就会抢占 CPU,对应用程序有较大影 ...
- Python基础——上节补充及数据类型
1.变量的创建过程 当我们创建一个变量name='oldboy'时,实际上是这样一个过程. 程序先开辟了一个内存空间,把变量的内容放进去,再让变量name指向'oldboy'所在的内存地址. 我们可以 ...
- NumPy 简单算术:加减乘除及其他运算
简单算术 你可以直接在 NumPy 数组之间使用算术运算符 + - * /,但本节讨论了一个扩展,其中我们有函数可以接受任何类似数组的对象,如列表.元组等,并根据条件执行算术运算. 条件算术:意味着我 ...
- 解锁LLMs的“思考”能力:Chain-of-Thought(CoT) 技术推动复杂推理的新发展
解锁LLMs的"思考"能力:Chain-of-Thought(CoT) 技术推动复杂推理的新发展 1.简介 Chain-of-Thought(CoT)是一种改进的Prompt技术, ...
- Excel表格Vlookup跨sheet取值,ISNA函数处理匹配不到的空字符串
Excel表格Vlookup跨sheet取值 =VLOOKUP($A2,Sheet2!$A$2:$D$15,2,FALSE) $A2 代表当前的Sheet1的单元格,数据类型需要与查找的单元格字段类型 ...
- 使用GET方法访问网站
使用GET方法访问网站 服务器接收get参数 server.py import flask app = flask.Flask(__name__) @app.route('/') def index( ...
- Isolution
<template> <div style="float:left;width: 100%; margin-left: 0"> <el-row > ...