当前位置:网站首页>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
边栏推荐
- 【深度学习】深度学习如何影响运筹学?
- [team PK competition] the task of this week has been opened | question answering challenge to consolidate the knowledge of commodity details
- Seaborn draws 11 histograms
- 网站页面禁止复制内容 JS代码
- 飞桨EasyDL实操范例:工业零件划痕自动识别
- 【机器人坐标系第一讲】
- How to install MySQL
- Summary of methods for finding intersection of ordered linked list sets
- composer安装报错:No composer.lock file present.
- 浏览器渲染原理以及重排与重绘
猜你喜欢
Jarvis OJ Telnet Protocol
Jarvis OJ webshell analysis
Flet教程之 11 Row组件在水平数组中显示其子项的控件 基础入门(教程含源码)
OneForAll安装使用
二叉树相关OJ题
有序链表集合求交集 方法 总结
[729. My Schedule i]
How to install MySQL
Flet tutorial 12 stack overlapping to build a basic introduction to graphic and text mixing (tutorial includes source code)
阈值同态加密在隐私计算中的应用:解读
随机推荐
数据访问 - EntityFramework集成
Spring Festival Limited "forget trouble in the year of the ox" gift bag waiting for you to pick it up~
[js] skill simplification if empty judgment
Iphone14 with pill screen may trigger a rush for Chinese consumers
How to set the WiFi password of the router on the computer
Flet tutorial 12 stack overlapping to build a basic introduction to graphic and text mixing (tutorial includes source code)
Explain in detail the functions and underlying implementation logic of the groups sets statement in SQL
Starkware: to build ZK "universe"
[729. My schedule I]
Summary of PHP pseudo protocol of cisp-pte
composer安装报错:No composer.lock file present.
有序链表集合求交集 方法 总结
Raspberry pie 4B installation pytorch1.11
[es6] 模板字符串内添加if判断或添加三元运算符判断
How does win11 change icons for applications? Win11 method of changing icons for applications
China Radio and television officially launched 5g services, and China Mobile quickly launched free services to retain users
极坐标扇图使用场景与功能详解
解决CMakeList find_package找不到Qt5,找不到ECM
Oneforall installation and use
Solution of vant tabbar blocking content