当前位置:网站首页>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
边栏推荐
- Keras crash Guide
- 2020-2022 two-year anniversary of creation
- Get ready for the pre-season card game MotoGP ignition champions!
- 中国广电正式推出5G服务,中国移动赶紧推出免费服务挽留用户
- Enter a command with the keyboard
- 挖财股票开户安全吗?怎么开股票账户是安全?
- Games101 notes (III)
- DeSci:去中心化科学是Web3.0的新趋势?
- C# TCP如何限制单个客户端的访问流量
- How was the middle table destroyed?
猜你喜欢

Data access - entityframework integration
![[729. My schedule I]](/img/e3/32914227d00cf7595ee850e60f2b72.png)
[729. My schedule I]

调查显示传统数据安全工具面对勒索软件攻击的失败率高达 60%

Pspnet | semantic segmentation and scene analysis

采用药丸屏的iPhone14或引发中国消费者的热烈抢购

"21 days proficient in typescript-3" - install and build a typescript development environment md

File operation --i/o

Jarvis OJ 简单网管协议

Clear restore the scene 31 years ago, volcanic engine ultra clear repair beyond classic concert

Games101 notes (III)
随机推荐
npm安装
[61dctf]fm
PHP strict mode
Enter a command with the keyboard
[deep learning] [original] let yolov6-0.1.0 support the txt reading dataset mode of yolov5
Etcd 构建高可用Etcd集群
Global Data Center released DC brain system, enabling intelligent operation and management through science and technology
數據訪問 - EntityFramework集成
[深度学习][原创]让yolov6-0.1.0支持yolov5的txt读取数据集模式
PHP talent recruitment system development source code recruitment website source code secondary development
Flet教程之 11 Row组件在水平数组中显示其子项的控件 基础入门(教程含源码)
飞桨EasyDL实操范例:工业零件划痕自动识别
文件操作--I/O
[brush questions] effective Sudoku
composer安装报错:No composer.lock file present.
Do sqlserver have any requirements for database performance when doing CDC
scratch五彩糖葫芦 电子学会图形化编程scratch等级考试三级真题和答案解析2022年6月
采用药丸屏的iPhone14或引发中国消费者的热烈抢购
Jarvis OJ webshell analysis
Domestic API management artifact used by the company