当前位置:网站首页>How can C TCP set heartbeat packets to be elegant?
How can C TCP set heartbeat packets to be elegant?
2022-07-05 16:55:00 【Ruo Qiming】
List of articles
One 、 explain
Why set the heartbeat ?
The heartbeat mechanism sends a customized message at regular intervals Structure ( Heartbeat bag ), Let the other person know that they are still alive , To ensure the validity of the connection . The data received and sent in the network are all from the operating system SOCKET To implement . But if this Socket It's disconnected , There must be problems when sending and receiving data . But how to judge whether this socket can still be used ? This requires creating a heartbeat mechanism in the system . Actually TCP A mechanism called heartbeat has been implemented for us in .
But this mechanism is limited by the operating system , And it's easy to make false positives . So it is rarely used by everyone .
The most used , Is to design the data package by yourself , Then reserve the heartbeat format , When the other party receives the heartbeat packet , Just return the response package directly .
that , In this way , Let's use RRQMSocket Elegant realization .
Two 、 Assembly source code
2.1 Source location
2.2 documentation
The front page of the document
3、 ... and 、 install
Nuget install RRQMSocket that will do , See link blog for specific steps .
VS、Unity Installation and use Nuget package
Four 、 data format
4.1 Design data format
Before using heartbeat , The data format must be clear , Never confuse business data . Generally, it fits Plc When waiting for ready-made modules , They have a fixed data format , At this time, you can refer to Data processing adapter , Quickly parse data .
But in this article , There is no prescribed format , So we need to design a simple and efficient data format first .
as follows :
| Data length | data type | Load data |
|---|---|---|
| 2 byte (Ushort) | 1 byte (Byte) | n byte (<65535) |
4.2 Parse data format
class MyFixedHeaderDataHandlingAdapter : CustomFixedHeaderDataHandlingAdapter<MyRequestInfo>
{
public override int HeaderLength => 3;
protected override MyRequestInfo GetInstance()
{
return new MyRequestInfo();
}
}
class MyRequestInfo : IFixedHeaderRequestInfo
{
public DataType DataType {
get; set; }
public byte[] Data {
get; set; }
public int BodyLength {
get; private set; }
public bool OnParsingBody(byte[] body)
{
if (body.Length == this.BodyLength)
{
this.Data = body;
return true;
}
return false;
}
public bool OnParsingHeader(byte[] header)
{
if (header.Length == 3)
{
this.BodyLength = RRQMBitConverter.Default.ToUInt16(header, 0)-1;
this.DataType = (DataType)header[2];
return true;
}
return false;
}
public void Package(ByteBlock byteBlock)
{
byteBlock.Write((ushort)((this.Data == null ? 0 : this.Data.Length) + 1));
byteBlock.Write((byte)this.DataType);
byteBlock.Write(Data);
}
public byte[] PackageAsBytes()
{
using ByteBlock byteBlock = new ByteBlock();
this.Package(byteBlock);
return byteBlock.ToArray();
}
public override string ToString()
{
return $" data type ={
this.DataType}, data ={
(this.Data==null?"null":Encoding.UTF8.GetString(this.Data))}";
}
}
enum DataType : byte
{
Ping,
Pong,
Data
}
5、 ... and 、 Create an extension class
/// <summary>
/// A heartbeat counter extension .
/// </summary>
static class DependencyExtensions
{
public static readonly DependencyProperty HeartbeatTimerProperty =
DependencyProperty.Register("HeartbeatTimer", typeof(Timer), typeof(DependencyExtensions), null);
public static bool Ping<TClient>(this TClient client)where TClient:ITcpClientBase
{
try
{
client.Send(new MyRequestInfo() {
DataType = DataType.Ping }.PackageAsBytes());
return true;
}
catch(Exception ex)
{
client.Logger.Exception(ex);
}
return false;
}
public static bool Pong<TClient>(this TClient client) where TClient : ITcpClientBase
{
try
{
client.Send(new MyRequestInfo() {
DataType = DataType.Pong }.PackageAsBytes());
return true;
}
catch (Exception ex)
{
client.Logger.Exception(ex);
}
return false;
}
}
6、 ... and 、 Create heartbeat plug-in class
class HeartbeatAndReceivePlugin : TcpPluginBase
{
private readonly int m_timeTick;
[DependencyInject(1000*5)]
public HeartbeatAndReceivePlugin(int timeTick)
{
this.m_timeTick = timeTick;
}
protected override void OnConnecting(ITcpClientBase client, ClientOperationEventArgs e)
{
client.SetDataHandlingAdapter(new MyFixedHeaderDataHandlingAdapter());// Setup adapter .
base.OnConnecting(client, e);
}
protected override void OnConnected(ITcpClientBase client, RRQMEventArgs e)
{
if (client is ISocketClient)
{
return;// It can be judged here , If it is a server , Do not use heartbeat .
}
if (client.GetValue<Timer>(DependencyExtensions.HeartbeatTimerProperty) is Timer timer)
{
timer.Dispose();
}
client.SetValue(DependencyExtensions.HeartbeatTimerProperty,new Timer((o)=>
{
client.Ping();
},null,0, m_timeTick));
base.OnConnected(client, e);
}
protected override void OnDisconnected(ITcpClientBase client, ClientDisconnectedEventArgs e)
{
base.OnDisconnected(client, e);
if (client.GetValue<Timer>(DependencyExtensions.HeartbeatTimerProperty) is Timer timer)
{
timer.Dispose();
client.SetValue(DependencyExtensions.HeartbeatTimerProperty,null);
}
}
protected override void OnReceivedData(ITcpClientBase client, ReceivedDataEventArgs e)
{
if (e.RequestInfo is MyRequestInfo myRequest)
{
client.Logger.Message(myRequest.ToString());
if (myRequest.DataType== DataType.Ping)
{
client.Pong();
}
}
base.OnReceivedData(client, e);
}
}
7、 ... and 、 test 、 start-up
class Program
{
static TcpService service = new TcpService();
static TcpClient tcpClient = new TcpClient();
static void Main(string[] args)
{
ConsoleAction consoleAction = new ConsoleAction();
service.Setup(new RRQMConfig()// Load configuration
.SetListenIPHosts(new IPHost[] {
new IPHost("127.0.0.1:7789"), new IPHost(7790) })// Listen to two addresses at the same time
.SetMaxCount(10000)
.UsePlugin()
.SetThreadCount(10))
.Start();// start-up
service.AddPlugin<HeartbeatAndReceivePlugin>();
service.Logger.Message(" Server started successfully ");
tcpClient.Setup(new RRQMConfig()
.SetRemoteIPHost(new IPHost("127.0.0.1:7789"))
.UsePlugin()
.SetBufferLength(1024 * 10));
tcpClient.AddPlugin<HeartbeatAndReceivePlugin>();
tcpClient.Connect();
tcpClient.Logger.Message(" Client successfully connected ");
consoleAction.OnException += ConsoleAction_OnException;
consoleAction.Add("1", " Send a heartbeat ", () =>
{
tcpClient.Ping();
});
consoleAction.Add("2", " send data ", () =>
{
tcpClient.Send(new MyRequestInfo()
{
DataType = DataType.Data,
Data = Encoding.UTF8.GetBytes(Console.ReadLine())
}
.PackageAsBytes());
});
consoleAction.ShowAll();
while (true)
{
consoleAction.Run(Console.ReadLine());
}
}
private static void ConsoleAction_OnException(Exception obj)
{
Console.WriteLine(obj);
}
}
8、 ... and 、 effect

this paper Example demo
边栏推荐
- Basic introduction to the control of the row component displaying its children in the horizontal array (tutorial includes source code)
- Sentinel-流量防卫兵
- 【学术相关】多位博士毕业去了三四流高校,目前惨不忍睹……
- Summary of methods for finding intersection of ordered linked list sets
- Solution of vant tabbar blocking content
- 为季前卡牌游戏 MotoGP Ignition Champions 做好准备!
- Raspberry pie 4B installation pytorch1.11
- 浏览器渲染原理以及重排与重绘
- 手机开证券账户安全吗?怎么买股票详细步骤
- C# TCP如何设置心跳数据包,才显得优雅呢?
猜你喜欢

American chips are no longer proud, and Chinese chips have successfully won the first place in emerging fields

Benji Banas membership pass holders' second quarter reward activities update list

Android privacy sandbox developer preview 3: privacy, security and personalized experience

深潜Kotlin协程(二十一):Flow 生命周期函数

Desci: is decentralized science the new trend of Web3.0?
![[deep learning] how does deep learning affect operations research?](/img/d8/a367c26b51d9dbaf53bf4fe2a13917.png)
[deep learning] how does deep learning affect operations research?

2020-2022两周年创作纪念日

Fleet tutorial 09 basic introduction to navigationrail (tutorial includes source code)

为季前卡牌游戏 MotoGP Ignition Champions 做好准备!

Jarvis OJ 远程登录协议
随机推荐
Bs-xx-042 implementation of personnel management system based on SSM
Jarvis OJ shell流量分析
Yarn common commands
详解SQL中Groupings Sets 语句的功能和底层实现逻辑
什么是ROM
拷贝方式之DMA
机器学习编译第2讲:张量程序抽象
Jarvis OJ Telnet Protocol
[61dctf]fm
Fleet tutorial 09 basic introduction to navigationrail (tutorial includes source code)
yarn 常用命令
The two ways of domestic chip industry chain go hand in hand. ASML really panicked and increased cooperation on a large scale
Data verification before and after JSON to map -- custom UDF
"21 days proficient in typescript-3" - install and build a typescript development environment md
Twig数组合并的写法
[deep learning] [original] let yolov6-0.1.0 support the txt reading dataset mode of yolov5
Flet教程之 11 Row组件在水平数组中显示其子项的控件 基础入门(教程含源码)
国产芯片产业链两条路齐头并进,ASML真慌了而大举加大合作力度
JSON转MAP前后数据校验 -- 自定义UDF
Win11如何给应用换图标?Win11给应用换图标的方法