When processing TCP data, we need to consider a problem of sticking packets. The so-called sticking packet is that the data received this time is not necessarily completely corresponding to the data sent by the other party. the data sent by the other Party may need to be received multiple times before it can be completed. The actual situation should be reviewed. To solve the packet ordering problem, a data analysis protocol must be developed for processing, there are two common solutions: one is based on the Terminator, and the other is to store the Message Size in a 4-byte header.
Notice on subcontracting
Although the method for processing the adhesive package is developed, the two methods still need to pay attention to several situations in terms of processing. The following uses a diagram to express the processing of several situations.
In fact, the most important concern is that the content of the separator or header description is stored in the receive data twice.
Implement a simple protocol analyzer
The component provides the above two subcontract handling methods. The basic classes are headsizeofpackage and eofdataofpackage. by continuing with the above two classes, you can simply send and receive object protocols; if the two are not suitable, a new protocol analysis class can be derived from the package to meet the actual needs. next, a simple object protocol analyzer is implemented by inheriting headsizeofpackage. The related package implementation is as follows:
Public class headsizepackage: beetle. headsizeofpackage {public headsizepackage (beetle. tcpchannel channel): Base (Channel) {} Private Static dictionary <string, Smark. core. instancehandler> mtypes = new dictionary <string, Smark. core. instancehandler> (256); public static void loadassembly (system. reflection. assembly) {foreach (type in assembly. gettypes () {If (type. getinterface ("beetle. I Message ")! = NULL & type. isclass) {mtypes [type. name] = new Smark. core. instancehandler (type) ;}}} protected override beetle. iMessage readmessagebytype (beetle. bufferreader reader, out object typetag) {typetag = reader. readintostring (); Smark. core. instancehandler handler; If (mtypes. trygetvalue (string) typetag, out handler) {return (beetle. iMessage) handler. instance ();} return NULL;} protected override void writemessagetype (beetle. iMessage MSG, beetle. bufferwriter writer) {writer. writeshortstring (MSG. getType (). name );}}
After inheriting headsizeofpackage, we mainly rewrite the two methods: readmessagebytype, which reads the message name from bufferreader and returns the specific message object. writemessagetype is the name of the written message. the two methods are mainly used to write the Message Type tag and return the message object according to the tag. after the protocol analysis is completed, the object protocol should be developed. The following is a simple registration protocol implementation:
Class register: beetle. iMessage {public string name; Public String email; Public datetime responsetime; Public void load (beetle. bufferreader reader) {name = reader. readstring (); email = reader. readstring (); responsetime = reader. readdate ();} public void save (beetle. bufferwriter writer) {writer. write (name); writer. write (email); writer. write (responsetime );}}
Build the TCP server with the object meanings
Constructing an object-based TCP server in beetle is also very simple. You only need beetle. serverbase <t>, while generic parameters are specific protocol analyzers.
Class program: beetle. serverbase <beetle. packages. headsizepackage> {protected override void onconnected (Object sender, beetle. channeleventargs e) {base. onconnected (sender, e); console. writeline ("{0} connected", E. channel. endpoint);} protected override void ondisposed (Object sender, beetle. channeldisposedeventargs e) {base. ondisposed (sender, e); console. writeline ("{0} disposed", E. channel. endpoint);} protected override void onerror (Object sender, beetle. channelerroreventargs e) {base. onerror (sender, e); console. writeline ("{0} error {1}", E. channel. endpoint, E. exception. message);} protected override void onmessagereceive (beetle. packetrecievemessagerargs e) {register Reg = (Register) E. message; Reg. responsetime = datetime. now; console. writeline ("Name: {0} Email: {1}", Reg. name, Reg. email); E. channel. send (REG );}
Just like constructing a common TCP service, you can rewrite the corresponding processing method. However, one of the methods is onmessagereceive, which mainly includes received messages and the corresponding socket channel tcpchannel. previously, only one register object message was defined. Here, the relevant message is obtained and the responsetime is set to the current time and then returned to the corresponding client.
Build a client for message Interaction
The client is created using the tcpserver. createclient <t> method. The generic parameter corresponds to the protocol analyzer.CodeAs follows:
Channel = beetle. tcpserver. createclient <beetle. packages. headsizepackage> (txtipaddress. text, 9450, onreceive); channel. channeldisposed + = ondisposed; channel. channelerror + = onerror; channel. beginreceive ();
Private void onreceive (beetle. packetrecievemessagerargs e) {register Reg = (Register) E. message; invoke (new action <register> (r => {txtremail. TEXT = R. email; txtrname. TEXT = R. name; txtresponsetime. TEXT = R. responsetime. tostring () ;}, REG) ;}private void ondisposed (Object sender, beetle. channeleventargs e) {invoke (new action <beetle. channeleventargs> (S => {txtstatus. TEXT = "disconnect! ";}), E) ;}private void onerror (Object sender, beetle. channelerroreventargs e) {invoke (new action <beetle. channelerroreventargs> (r => {txtstatus. TEXT = R. exception. message;}), e );}
After the connection is built, bind related events and enter the data receiving mode. After the connection is created, the object protocol can be sent.
Register Reg = new register (); Reg. Name = txtname. Text; Reg. Email = txtemail. Text; Channel. Send (REG );
Running Effect
Download Code: Code
Summary
Through the beetle protocol analyzer, you can simply solve the TCP packet Sticking Problem and flexibly support different protocols, the following sections describe how to expand a message configurator to implement processing. net binary sequence filling, XML serialization, prorobuf, amf3 and other data objects.