This article mainly introduces the common protocol implementation template and Fixedsizereceivefilter example. Have a good reference value, follow the small series together to see it
The protocol resolution inside the socket is the most complicated part of the socket Communication program design, and if your application layer protocol is poorly designed or implemented, the common sticky packets in the socket can be difficult to avoid. SuperSocket has built-in command-line protocol Commandlineprotocol, if you use protocols in other formats, you must implement your own custom protocol customprotocol. After reading a document, you may find it not easy to use SuperSocket to implement your custom protocol. To make this easier, SuperSocket provides a number of common protocol resolution tools that you can use to implement your own communication protocols simply and quickly:
Terminatorreceivefilter (SuperSocket.SocketBase.Protocol.TerminatorReceiveFilter, Supersocket.socketbase)---Terminator protocol
Countspliterreceivefilter (SuperSocket.Facility.Protocol.CountSpliterReceiveFilter, supersocket.facility)---fixed number separator protocol
Fixedsizereceivefilter (SuperSocket.Facility.Protocol.FixedSizeReceiveFilter, supersocket.facility)---Fixed request size protocol
Beginendmarkreceivefilter (SuperSocket.Facility.Protocol.BeginEndMarkReceiveFilter, supersocket.facility)---with end-to-end character protocol
Fixedheaderreceivefilter (SuperSocket.Facility.Protocol.FixedHeaderReceiveFilter, supersocket.facility)---Header format fixed and contains content length protocol
1. Terminatorreceivefilter Terminator Protocol
The Terminator protocol and the command-line protocol are similar, and some protocols use a terminator to determine a request. For example, a protocol uses the two-character "# #" as the Terminator, so you can use the class "Terminatorreceivefilterfactory":
Terminator Protocol Terminatorprotocolserver:
public class terminatorprotocolserver:appserver{public terminatorprotocolserver () : Base (new Terminatorreceivefilterfactory ("# #")) {}}
Implement your receive filter (Receivefilter) based on Terminatorreceivefilter:
public class yourreceivefilter:terminatorreceivefilter<yourrequestinfo>{//more code}
Implement your receive filter factory (receivefilterfactory) to create an accept filter instance:
public class yourreceivefilterfactory:ireceivefilterfactory<yourrequestinfo>{//more code}
2. Countspliterreceivefilter Fixed Number Separator protocol
Some protocols define requests such as "#part1 #part2#part3#part4#part5#part6#part7#" in such a format. Each request has 7 sections separated by a ' # '. The implementation of this Protocol is very simple:
<summary>///Request Format: #part1 #part2#part3#part4#part5#part6#part7#///</summary>public class countspliterappserver:appserver{public Countspliterappserver () : Base (New Countspliterreceivefilterfactory ( byte) ' # ', 8))//8 separators, 7 parameters. In addition to using the default filter factory, you can also reference the previous instance custom protocol {}}
3. Fixedsizereceivefilter Fixed Request size protocol
In such a protocol, all requests are of the same size. If each of your requests is a string of 8 characters, such as "HUANG LI", what you should do is to implement a receive filter (Receivefilter) like the following code:
Class myreceivefilter:fixedsizereceivefilter<stringrequestinfo>{public Myreceivefilter () : Base (8)// Incoming fixed request size {} protected override Stringrequestinfo Processmatchedrequest (byte[] buffer, int offset, int length, bool Tobec opied) { //todo: Constructs the request instance through the parsed data and returns}}
Then use this accept filter (Receivefilter) in your AppServer class:
public class myappserver:appserver{Public myappserver () : base (New defaultreceivefilterfactory< Myreceivefilter, stringrequestinfo> ())//using the default Accept Filter factory (defaultreceivefilterfactory) {}}
4, Beginendmarkreceivefilter with the beginning and end of the agreement
There are fixed start and end tags in each request for this type of protocol. For example, I have an agreement that all of its messages follow this format "&xxxxxxxxxxxxxx#". So, in this case, "&" is the start tag, "#" is the end tag, so your acceptance filter can be defined like this:
Class myreceivefilter:beginendmarkreceivefilter<stringrequestinfo>{//Start and end tags can also be two or more than two bytes private readonly Static byte[] Beginmark = new byte[] {(byte) ' & '}; Private readonly static byte[] Endmark = new byte[] {(byte) ' # '}; Public Myreceivefilter () : Base (Beginmark, Endmark)//Incoming start tag and end tag {} protected override Stringrequestinfo Processmatchedrequest (byte[] readbuffer, int offset, int length) { //todo: Constructs the request instance through the parsed data and returns}}
Then use this accept filter (Receivefilter) in your AppServer class:
public class myappserver:appserver{Public myappserver () : base (New defaultreceivefilterfactory< Myreceivefilter, stringrequestinfo> ())//using the default Accept Filter factory (defaultreceivefilterfactory) {}}
5. Fixedheaderreceivefilter header format fixed and contains content length protocol
This protocol defines a request as two parts, and the first part defines the basic information including the second part length, and so on. We usually call the first part head.
For example, we have one such protocol: the header contains 6 bytes, the first 4 bytes are used to store the requested name, and the last two bytes are used to represent the length of the request body:
+-------+---+-------------------------------+///|request| L | | /// | Name | e | Request Body |///| (4) | n | | /// | | (2) | | /// +-------+---+-------------------------------+
With SuperSocket, you can implement this protocol very conveniently:
Class myreceivefilter:fixedheaderreceivefilter<binaryrequestinfo>{public Myreceivefilter () : Base (6) {} protected override int Getbodylengthfromheader (byte[] header, int offset, int length) { return (int) Header[offset + 4] * + (int) Header[offset + 5]; } protected override Binaryrequestinfo Resolverequestinfo (arraysegment<byte> header, byte[] bodybuffer, int Offset, int length) { return new Binaryrequestinfo (Encoding.UTF8.GetString (header). Array, header. Offset, 4), Bodybuffer.clonerange (offset, length)); }}
You need to implement your own receive filter based on the class Fixedheaderreceivefilter.
The 6 passed in to the parent class constructor represents the length of the head;
The method "Getbodylengthfromheader (...)" should return the length of the request body according to the received header;
Method Resolverequestinfo (...) "The instance of your request type should be returned based on the request header and the request body you received.
Actual usage scenarios:
Here are the five types of protocol templates you've already learned and know about formatting. Next look at a network example:
Communication protocol Format:
After seeing the protocol is sent 16 in the tangled client, the server how to receive, 16 binary messages are as follows:
26 01 00 19 4E 4A 30 31 31 01 44 41 31 31 32 00 07 00 00 00 00 00 00 34 23
16 into the system, 10 or more, the other into the system, and ultimately converted to byte[], in fact, when processing data, send the past data can be converted into byte[], so the service as long as the resolution byte[] array on the line. You can get the data you want by parsing the protocol. The following example uses Fixedsizereceivefilter, the code is as follows:
Based on the above communication protocol, start to implement the parsing:
The first step, defining a data structure that is appropriate for the Protocol
Using system;using system.collections.generic;using system.linq;using system.text;using System.Threading.Tasks;/*** Author: Twilight before dawn * CLR version: 4.0.30319.42000* created on: 2017-01-23 21:12:30* 2017* Description: Protocol packet * * Modification history: *******************************************************************/namespace supersocketdemo{public class Hldata {//<summary>///Start sign///</summary> public char Head {get; set; }///<summary>///package data///</summary> public byte Ping {get; set;} <summary>///Data length///</summary> public ushort Lenght {get; set;} <summary>///terminal ID///</summary> public uint FID {get; set;} <summary>////target type///</summary> public byte type {get; set;} <summary>///Forwarding terminal ID///</summary> public uint SID {get; set;} <summary>////Send count///</summary> public ushort Sendcount {get; set;} <summary>///reserved fields///</summary> public byte[] Retain {get; set;} <summary>//XOR Check///</summary> public byte Check {get; set;} <summary>///end symbol///</summary> public char end {get; set;} public override string ToString () {return string. Format ("start symbol: {0}, packet data: {1}, data length: {2}, terminal id:{3}, Target type: {4}, forwarding terminal id:{5}, send packet count: {6}, reserved field: {7}, XOR: {8} , lenght, FID, Type, SID, Sendcount, Retain, Check, End); }}}hldata
Step two, establish a requestinfo to receive the server data
Using system;using system.collections.generic;using system.linq;using system.text;using System.Threading.Tasks; Using supersocket.socketbase.protocol;/***************************************************************** Author: Twilight before dawn * CLR version: 4.0.30319.42000* created: 2017-01-22 21:03:31* 2017* Description: Data Request * * Revision history: ************************************ /namespace supersocketdemo{public class hlprotocolrequestinfo:requestinfo< hldata> {public hlprotocolrequestinfo (hldata hldata) { //If you need to use a command-line protocol, the command class name Hldata the same Initialize ("Hldata", Hldata); } }}hlprotocolrequestinfo class
The third step, Fixedsize protocol resolution
Using system;using system.collections.generic;using system.linq;using system.text;using System.Threading.Tasks; Using supersocket.socketbase.protocol;using supersocket.facility.protocol;using supersocket.common;/************* Author: Twilight before dawn * CLR version: 4.0.30319.42000* created: 2017-01-22 21:06:01* 2017* Description: Protocol resolution class, fixed request-SIZE protocol * * Modified history: *******************************************************************/namespace supersocketdemo{//<summary>///Fixed request size protocol (frame format hlprotocolrequestinfo)///</summary> public class hlprotocolreceivefilter:fixedsizereceivefilter
Fourth step, set up agreement factory Hlreceivefilterfactory
Using system;using system.collections.generic;using system.linq;using system.text;using System.Threading.Tasks; Using supersocket.socketbase;using supersocket.socketbase.protocol;using system.net;/**************************** Author: Twilight before dawn * CLR version: 4.0.30319.42000* creation time: 2017-01-23:22:01:25* 2017* Description: Protocol Factory * * Revision history: *******************************************************************/namespace SuperSocketDemo{public class hlreceivefilterfactory:ireceivefilterfactory
Fifth step, custom hlprotocolsession inheritance Appsession
Using supersocket.socketbase;using supersocket.socketbase.protocol;using system;/******************************** Author: Twilight before dawn * CLR version: 4.0.30319.42000* created: 2017-01-22 21:15:11* 2017* Description: Custom hlprotocolsession** modification History: *******************************************************************/namespace supersocketdemo{public class Hlprotocolsession:appsession
Sixth step, custom Hlprotocolserver inheritance AppServer
Using system;using system.collections.generic;using system.linq;using system.text;using System.Threading.Tasks; Using supersocket.socketbase;using supersocket.socketbase.protocol;/******************************************** Author: Twilight before dawn * CLR version: 4.0.30319.42000* created: 2017-01-22 21:16:57* 2017* Description: Custom server** modification history: *******************************************************************/namespace supersocketdemo{public class Hlprotocolserver:appserver
The seventh step, plus the end-to-end protocol Hlbeginendmarkreceivefilter
Using system;using system.collections.generic;using system.linq;using system.text;using System.Threading.Tasks; Using supersocket.common;using supersocket.facility.protocol;/************************************************** Author: Twilight before dawn * CLR version: 4.0.30319.42000* created: 2017-01-23 22:07:03* 2017* Description: Protocol with a start and end character, "&" is the opening tag, "#" is a knot Bundle marker, start end tag defined by yourself * * Modify history: *******************************************************************/namespace supersocketdemo{public class Hlbeginendmarkreceivefilter:beginendmarkreceivefilter
step Eighth, service start and stop
Using system;using system.collections.generic;using system.linq;using system.text;using System.Threading.Tasks; Using supersocket.socketbase;using supersocket.socketbase.protocol;using supersocket.socketengine;/************** Author: Twilight before dawn * CLR version: 4.0.30319.42000* created: 2017-01-19 00:02:17* 2017* Description: Service start and stop entry * * Revision history: 2017-01-19 Adjust custom mysession and myserver* 2017-01-23 Communication protocol resolution, directly using the Ingress registration event ****************** /namespace supersocketdemo{class Program {//<summary>// /SuperSocket service start or stop///</summary>//<param name= "args" ></param> static void Main (string[] A RGS) {Console.WriteLine ("Please press any key to start SuperSocket service!"); Console.readkey (); Console.WriteLine (); var hlprotocolserver = new Hlprotocolserver (); Set port number int port = 2017; Start the app service port if (! Hlprotocolserver.setup (port)//Listening port at startup {Console.wriTeline ("Service port failed to start!"); Console.readkey (); Return } Console.WriteLine (); Register Connection Event Hlprotocolserver.newsessionconnected + = hlprotocolserver_newsessionconnected; Registration Request Event Hlprotocolserver.newrequestreceived + = hlprotocolserver_newrequestreceived; Register session Shutdown Event hlprotocolserver.sessionclosed + = hlprotocolserver_sessionclosed; Try to start the app service if (! Hlprotocolserver.start ()) {Console.WriteLine ("Service failed to start!"); Console.readkey (); Return } Console.WriteLine ("Server Status:" + HLProtocolServer.State.ToString ()); Console.WriteLine ("Service started successfully, please press ' E ' to stop the service!"); while (Console.readkey (). KeyChar! = ' E ') {Console.WriteLine (); Continue }//Stop service hlprotocolserver.stop (); Console.WriteLine ("Service has stopped!"); Console.readkey (); } static void Hlprotocolserver_sessionclosed (Hlprotocolsession session, SuperSocket.SocketBase.CloseReason value) { Console.WriteLine (session. REmoteendpoint.tostring () + "connection disconnected. Disconnect reason: "+ value"; } static void Hlprotocolserver_newsessionconnected (Hlprotocolsession session) {Console.WriteLine (session). Remoteendpoint.tostring () + "connected."); }///<summary>///The protocol does not have much complex logic, do not need to use the command mode, directly in this way can///</summary>//<param Name= "session "></param>//<param name=" Requestinfo "></param> private static void Hlprotocolserver_newreque Streceived (hlprotocolsession session, Hlprotocolrequestinfo Requestinfo) {Console.WriteLine (); Console.WriteLine ("Data Source:" + Session.) Remoteendpoint.tostring ()); Console.WriteLine ("Receive Data content:" +requestinfo.body); }}}program Class
Communication protocol requires the use of small tools for debugging, I am using the TCP/UDP port debugging tool Sockettool V2. You can download it directly. Send 16 message using hex mode, server output result: