同步操作将从 若汝棋茗/TouchSocket 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
合抱之木,生于毫末;九层之台,起于垒土。
简体中文 | English
对象池在RRQMSocket有很多应用,最主要的两个就是连接对象池和处理对象池。连接对象池就是当客户端成功连接时,首先会去连接对象池中找TcpSocketClient,然后没有的话,才会创建。如果哪个客户端掉线了,它的TcpSocketClient就会被回收。这也就是ID重用的原因。
然后就是处理对象池,在RRQMSocket中,接收数据的线程和IOCP内核线程是分开的,也就是比如说客户端给服务器发送了1w条数据,但是服务器收到后处理起来很慢,那传统的iocp肯定会放慢接收速率,然后通知客户端的tcp窗口,发生拥塞,然后让客户端暂缓发送。但是在RRQMSocket中会把收到的数据通过队列全都存起来,首先不影响iocp的接收,同时再分配线程去处理收到的报文信息,这样就相当于一个“泄洪湖泊”,能很大程度的提高处理数据的能力。
由于有处理对象池的存在,使多线程处理变得简单。在客户端连接完成时,会自动分配该客户端辅助类(TcpSocketClient)的消息处理逻辑线程,假如服务器线程数量为10,则第一个连接的客户端会被分配到0号线程中,第二个连接将被分配到1号线程中,以此类推,循环分配。当某个客户端收到数据时,会将数据排入当前线程所独自拥有的队列当中,并唤醒线程执行。
RRQMSocket的IOCP和传统也不一样的,以微软官方为例,使用MemoryBuffer开辟一块内存,然后均分,然后给每个会话分配一个区接收,等收到数据以后,再复制一份,然后把复制的数据抛出处理。而RRQMSocket是每次接收之前,从内存池拿一个可用内存块,然后直接用于接收,等收到数据以后,直接就把这个内存块抛出去了,这样就避免了复制操作,虽然只是细小的设计,但是在传输1000w次64kb的数据时,性能相差了10倍。所以也是基于此,文件传输时效率才会高。
相信大家都使用过其他的Socket产品,例如HPSocket,SuperSocket等,那么RRQMSocket在设计时也是借鉴了其他产品的优秀设计理念,数据处理适配器就是其中之一,但和其他产品的设计不同的是,RRQMSocket的适配器功能更加强大,它可以无视真实的数据,而模拟出想要的数据,例如:可以对数据进行预处理,从而解决数据分包。粘包的问题,也可以直接解析HTTP协议,经过适配器处理后传回一个HttpRequest对象等。
在RRQMSocket中处理TCP粘包、分包问题是非常简单的。只需要更改不同的数据处理适配器即可。例如:使用固定包头,只需要给TcpSocketClient和TcpClient赋值FixedHeaderDataHandlingAdapter的实例即可。同样对应的处理器也有固定长度 、 终止字符分割 等。
名称 | 版本(Nuget Version) | 下载(Nuget Download) | 描述 |
---|---|---|---|
RRQMCore | RRQMCore是为RRQM系提供基础服务功能的库,其中包含:内存池、对象池、等待逻辑池、AppMessenger、3DES加密、Xml快速存储、运行时间测量器、文件快捷操作、高性能序列化器、规范日志接口等。 | ||
RRQMMVVM | RRQMMVVM是超轻简的MVVM框架,但是麻雀虽小,五脏俱全。 | ||
RRQMSkin | RRQMSkin是WPF的控件样式库,其中包含: 无边框窗体 、 圆角窗体 、 水波纹按钮 、 输入提示筛选框 、 控件拖动效果 、圆角图片框、 弧形文字 、 扇形元素 、 指针元素 、 饼图 、 时钟 、 速度表盘 等。 |
详细过程请阅读API文档,以下仅简单示例。
创建RRQMTcpService
RRQMTcpService是对TcpService的简单封装,指定辅助类为RRQMSocketClient,在辅助类中不做任何数据处理,仅将数据在RRQMTcpService中抛出。
RRQMTcpService service = new RRQMTcpService();
//订阅事件
//service.ClientConnected += Service_ClientConnected;//订阅连接事件
//service.ClientDisconnected += Service_ClientDisconnected;//订阅断开连接事件
//service.CreatSocketCliect += Service_CreatSocketCliect;//订阅创建辅助类事件,可直接设置其他属性。
//service.OnReceived += Service_OnReceived;//可直接订阅收到数据事件。
//属性设置
service.IsCheckClientAlive = true;//使用空包检验活性,不会对数据有任何影响。
service.BufferLength = 1024;//设置缓存池大小,该数值在框架中经常用于申请ByteBlock,所以该值会影响内存池效率。
service.IDFormat = "TcpSocketClient_{0}";//设置分配ID的格式, 格式必须符合字符串格式,至少包含一个补位, 初始值为“{0}-TCP”
service.Logger = new Log();//设置内部日志记录器,默认日志是控制台输出。
service.MaxCount = 1000;//设置最大连接数,可动态设置,当已连接数超过设置数值时,将主动断开客户端。
//方法
service.Bind(7789, 2);//绑定监听,可绑定Ipv6,可监听所有地址。
Console.WriteLine("RRQMTcpService绑定成功");
创建TokenTcpService
TokenTcpService是继承于TcpService的功能扩展服务器,该服务器的主要功能是通过验证“口令”对连接的客户端进行筛选,及时的将不允许连接、恶意连接、不安全连接的客户端拒之门外,也可以实现租户模式。
TokenTcpService<MyTcpSocketClient> service = new TokenTcpService<MyTcpSocketClient>();
service.VerifyToken = "ABC";
//方法
service.Bind(7789, 2);//绑定监听,可绑定Ipv6,可监听所有地址。
Console.WriteLine("TokenTcpService绑定成功");
注意: 使用该服务器必须遵循连接协议,或使用专属客户端(TokenTcpClient)连接。
创建TcpClient
TcpClient可与任意服务器进行连接、收发,处理数据,也可以更加方便的处理粘包和分包,亦或者解析数据结构。
TcpClient client = new TcpClient();
//属性
client.BufferLength = 1024;//设置缓存池大小,该数值在框架中经常用于申请ByteBlock,所以该值会影响内存池效率。
client.Logger = new Log();//设置内部日志记录器,默认日志是控制台输出。
client.DataHandlingAdapter = new NormalDataHandlingAdapter();//数据处理适配器,可用于处理粘包、解析对象。
//事件
//client.ConnectedService += Client_ConnectedService;
//client.DisconnectedService += Client_DisconnectedService;
//client.OnReceived += Client_OnReceived;
//方法
client.Connect(new IPHost("127.0.0.1:7789"));//连接
Console.WriteLine("连接成功");
client.Send(Encoding.UTF8.GetBytes("若汝棋茗"));//发送数据
Console.WriteLine("发送成功");
创建TokenTcpClient
TokenTcpClient client = new TokenTcpClient();
//属性
client.VerifyToken="ABC";//设置链接口令。
client.BufferLength = 1024;//设置缓存池大小,该数值在框架中经常用于申请ByteBlock,所以该值会影响内存池效率。
client.Logger = new Log();//设置内部日志记录器,默认日志是控制台输出。
client.DataHandlingAdapter = new NormalDataHandlingAdapter();//数据处理适配器,可用于处理粘包、解析对象。
//事件
//client.ConnectedService += Client_ConnectedService;
//client.DisconnectedService += Client_DisconnectedService;
//client.OnReceived += Client_OnReceived;
//方法
client.Connect(new IPHost("127.0.0.1:7789"));//连接
Console.WriteLine("连接成功");
client.Send(Encoding.UTF8.GetBytes("若汝棋茗"));//发送数据
Console.WriteLine("发送成功");
数据处理适配器的主要作用就是对发送、接收的数据进行封装和解析。在RRQMSocket中,可以利用数据处理适配器解决粘包、分包问题,也能解析Http数据报文。
类型
客户端使用
客户端比较简单,直接对其赋值即可。
client.DataHandlingAdapter = new NormalDataHandlingAdapter();//数据处理适配器,可用于处理粘包、解析对象。
服务器使用
在服务器使用适配器时,必须保证每个TcpSocketClient都拥有一个单独实例的适配器,所以可以订阅CreatSocketCliect事件,然后又因为RRQMSocket中有连接对象池,所以最好进行新创建判断,然后再创建实例化,避免多次实例化赋值带来的性能问题。
private static void Service_CreatSocketCliect(RRQMSocketClient arg1, CreatOption arg2)
{
if (arg2.NewCreate)
{
arg1.DataHandlingAdapter = new NormalDataHandlingAdapter();
}
}
如果是自定义继承的TcpSocketClient,可以重写Create方法。
注意:在构造函数内赋值适配器无效,会被Create方法覆盖
public class MyTcpSocketClient : TcpSocketClient
{
/// <summary>
/// 初次创建对象,效应相当于构造函数,但是调用时机在构造函数之后,可覆盖父类方法
/// </summary>
public override void Create()
{
this.DataHandlingAdapter = new NormalDataHandlingAdapter();//普通TCP报文处理器
//this.DataHandlingAdapter = new FixedHeaderDataHandlingAdapter();//固定包头TCP报文处理器
//this.DataHandlingAdapter = new FixedSizeDataHandlingAdapter(1024);//固定长度TCP报文处理器
//this.DataHandlingAdapter = new TerminatorDataHandlingAdapter(1024, "\r\n");//终止字符TCP报文处理器
}
}
以下进行简单示例,详细使用见文件传输入门
FileService fileService = new FileService();
fileService.VerifyToken ="123ABC";
fileService.BreakpointResume = true;//支持断点续传
try
{
fileService.Bind(7789,2);//直接监听7789端口号。多线程,默认为1,此处设置线程数量为2
/* 订阅相关事件
fileService.ClientConnected += FileService_ClientConnected;
fileService.ClientDisconnected += FileService_ClientDisconnected;
fileService.BeforeTransfer += FileService_BeforeTransfer ;
fileService.FinishedTransfer += FileService_FinishedTransfer ;
fileService.ReceiveSystemMes += FileService_ReceiveSystemMes;
*/
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
先初始化客户端。
FileClient fileClient = new FileClient();
//订阅事件
//fileClient.TransferFileError += FileClient_TransferFileError;
//fileClient.BeforeFileTransfer += this.FileClient_BeforeFileTransfer; ;
//fileClient.FinishedFileTransfer += this.FileClient_FinishedFileTransfer; ;
//fileClient.DisconnectedService += FileClient_DisConnectedService;
//fileClient.ReceiveSystemMes += this.FileClient_ReceiveSystemMes;
//fileClient.ConnectedService += this.FileClient_ConnectedService;
//fileClient.FileTransferCollectionChanged += this.FileClient_FileTransferCollectionChanged;
fileClient.Connect(new IPHost("127.0.0.1:7789"));//连接服务器。
调用RequestTransfer进行传输文件。此方法可上传,也可下载。请求成功后会将传输排入队列,然后依次传输。
上传
//restart属性可以自由设定。
//breakpointResume也可自由指定,但最好是从fileClient获取属性。
UrlFileInfo urlFileInfo = UrlFileInfo.CreatUpload("C:/1.txt", restart: true, breakpointResume: this.fileClient.BreakpointResume);
fileClient.RequestTransfer(urlFileInfo);
下载
//restart属性可以自由设定。
UrlFileInfo urlFileInfo = UrlFileInfo.CreatDownload("C:/1.txt", restart: true);
fileClient.RequestTransfer(urlFileInfo);
fileClient.PauseTransfer();//暂停传输
fileClient.ResumeTransfer();//恢复传输
foreach (var item in fileClient.FileTransferCollection)
{
fileClient.CancelTransfer(item);//从传输列表中获得传输信息,然后取消该传输任务
break;
}
fileClient.StopThisTransfer();//停止当前下载
fileClient.StopAllTransfer();//停止所有下载
fileClient.SendSystemMessage("RRQM");//发送系统消息
fileClient.SendBytesWaitReturn(new byte[10],0,10);//发生字节数组并等待返回
Demo位置: RRQMBox
说明: 可以看到,图一正在上传一个Window的系统镜像文件,大约4.2Gb,传输速度已达到346Mb/s,这是因为服务器和客户端在同一电脑上,磁盘性能限制导致的。其次,GC基本上没有释放,性能非常强悍,图二是下载文件,性能依旧非常强悍。
RPC框架是所有远程过程调用的微服务管理平台,在该平台的托管下,使多种协议、多种序列化方式调用成为可能。目前可使用RRQMRPC、WebApi、XmlRpc、JsonRpc共同调用。
特点
新建类文件,继承于ServerProvider,并将其中公共方法标识为RRQMRPCMethod即可。
public class Server: ServerProvider
{
[RRQMRPCMethod]
public string TestOne(string str)
{
return "若汝棋茗";
}
}
RPCService rpcService = new RPCService();
rpcService.RegistAllService();//注册所有服务
TcpRPCParser tcpRPCParser = new TcpRPCParser();
tcpRPCParser.SerializeConverter = new BinarySerializeConverter();
tcpRPCParser.Bind(7789, 5);
tcpRPCParser.NameSpace = "RRQMTest";
Console.WriteLine("TCP解析器添加完成");
rpcService.AddRPCParser("TcpParser", tcpRPCParser);
rpcService.OpenRPCServer();
Console.WriteLine("RPC启动完成");
Console.ReadKey();
首先得下载RRQMRPCVSIX插件,然后安装插件,成功后右击任意项目即可看见“重新引用RRQMRPC”条目。
然后点击,弹出窗口,输入IP及端口,点击确认,即可下载完成引用,此时会在项目下生成RRQMRPC文件夹,里面含有代理文件。
RPCClient client = new RPCClient();
client.InitializedRPC(new IPHost("127.0.0.1:7789"));
Server server = new Server(client);
string mes=server.TestOne("RRQM");//调用
说明:
图一、图二、图三分别为UDP无反馈调用
、TCP有反馈调用
、TCP连接池有反馈调用
。调用次数均为10w次,调用性能非常nice。在无反馈中,吞吐量达14.28w,在有反馈中达2.72w,简直秒杀WCF(WCF使用http协议,在本机测试吞吐量为310)
WebApi功能,目前仅仅适用于Api调用,不具备MVC全部功能。
新建类文件,继承于ServerProvider,使用Rount属性指定路由规则,同时将其中公共方法标识为Route即可。同时也可制定路由规则。
[Route("/[controller]/[action]")]
public class Server: ServerProvider
{
[Route]
public string TestOne(string str)
{
return "若汝棋茗";
}
}
RPCService rpcService = new RPCService();
rpcService.RegistAllService();//注册所有服务
WebApiParser webApiParser = new WebApiParser();
webApiParser.Bind(7792, 5);
Console.WriteLine("webApiParser解析器添加完成");
rpcService.AddRPCParser("webApiParser", webApiParser);
rpcService.OpenRPCServer();
Console.WriteLine("RPC启动完成");
Console.ReadKey();
此时即可使用PostManagent测试,也可以直接使用浏览器访问。
注意:默认数据格式是xml,如需Json,请详看说明文档。
完美支持XmlRpc数据类型,类型嵌套,Array等。
新建类文件,继承于ServerProvider,同时将其中公共方法标识为XmlRpc即可。
public class Server: ServerProvider
{
[XmlRpc]
public string TestOne(string str)
{
return "若汝棋茗";
}
}
RPCService rpcService = new RPCService();
rpcService.RegistAllService();//注册所有服务
XmlRpcParser xmlRpcParser = new XmlRpcParser();
xmlRpcParser.Bind(7793, 5);
Console.WriteLine("xmlRpcParser解析器添加完成");
rpcService.AddRPCParser("xmlRpcParser", xmlRpcParser);
rpcService.OpenRPCServer();
Console.WriteLine("RPC启动完成");
Console.ReadKey();
此时即可使用CookComputing.XmlRpcV2测试。
新建类文件,继承于ServerProvider,同时将其中公共方法标识为JsonRpc即可。
public class Server: ServerProvider
{
[JsonRpc]
public string TestOne(string str)
{
return "若汝棋茗";
}
}
RPCService rpcService = new RPCService();
rpcService.RegistAllService();//注册所有服务
JsonRpcParser jsonRpcParser = new JsonRpcParser();
jsonRpcParser.Bind(7793, 5);
Console.WriteLine("jsonRpcParser解析器添加完成");
rpcService.AddRPCParser("jsonRpcParser", jsonRpcParser);
rpcService.OpenRPCServer();
Console.WriteLine("RPC启动完成");
Console.ReadKey();
此时即可使用Json格式数据调用RPC。
TcpClient tcpClient = new TcpClient();
//tcpClient.OnReceived += TcpClient_OnReceived;//接收返回数据。
tcpClient.Connect(new IPHost("127.0.0.1:7793"));
tcpClient.Send(Encoding.UTF8.GetBytes("{\"jsonrpc\":\"2.0\",\"method\":\"TestOne\",\"params\":[5],\"id\":1}\r\n"));//此处必须包含“\r\n”。
谢谢大家对我的支持,如果还有其他问题,请加群QQ:234762506讨论。
您的支持就是我不懈努力的动力。打赏时请一定留下您的称呼。
赞助总金额:366.6¥
赞助名单:
(以下排名只按照打赏时间顺序)
1.Bobo Joker
2.UnitySir
3.Coffee
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。