All objects sent by the component must implement the iMessage interface to describe the serialization process of an object through the implementation interface. The advantage of custom read/write stream is that it can achieve better performance, however, the disadvantage is that the workload is large. in many application scenarios, the pursuit of performance is not the first, but the hope to save these troubles, in order to cope with this need components can implement a simple message adapter to complete such a function. the following describes how to implement the component pair through extension. net binary serialized object transfer support.
Define protocol format
For data interaction under TCP, a communication application protocol should be developed first. Because the component provides a basic Analyzer Based on the Terminator and header size description, it can be derived from this basic analysis coroutine. the following figure shows the details of the Protocol.
The protocol description is relatively simple. The message header contains four bytes to store the total length of the message, while the serialized data is the total length minus the first four digits.
Implement a specific analyzer and message Adapter
The analyzer can be implemented after the Protocol is developed. Because the first 4 bytes are used to describe the size, the analyzer can download and rewrite related methods from the headsizeofpackage base class. Complete implementationCodeAs follows:
Public class binaryformatterpackage: headsizeofpackage {public binaryformatterpackage () {} public binaryformatterpackage (tcpchannel channel): Base (Channel) {} public override object readcast (Object message) {return (messageadapter) message ). message;} public override object writecast (Object message) {messageadapter adapter = new messageadapter (); adapter. message = message; return adapter;} public override iMessage messageread (bufferreader reader) {iMessage MSG = NULL; object typetag; MSG = readmessagebytype (reader, out typetag ); if (MSG = NULL) Throw nettcpexception. typenotfound (typetag. tostring (); try {MSG. load (Reader);} catch (exception e) {nettcpexception err = nettcpexception. objectloaderror (typetag. tostring (), e); throw err;} return MSG;} protected override void writemessagetype (iMessage MSG, bufferwriter writer) {} protected override iMessage iterator (bufferreader reader, out object typetag) {typetag = "adapter"; return New messageadapter ();} class messageadapter: iMessage {public object message {Get; set;} public void load (bufferreader reader) {bytearraysegment bas = bytearraysegment; try {int COUNT = reader. readint32 (); reader. read (count-4, Bas); Using (system. io. memorystream stream = new system. io. memorystream (Bas. array, 0, Bas. count) {formatter formater = new formatter (); message = formater. deserialize (Stream) ;}} catch (exception E _) {Throw E _ ;}} public void save (bufferwriter writer) {bytearraysegment bas = bytearraysegment; try {using (system. io. memorystream stream = new system. io. memorystream (Bas. array) {formatter formater = new formatter (); formater. serialize (stream, message); Bas. setinfo (0, (INT) stream. position);} writer. write (Bas. array, 0, Bas. count);} catch (exception E _) {Throw E _;} [threadstatic] Private Static bytearraysegment mbytearraysegment = NULL; Public bytearsegrayment bytearraysegment {get {If (mbytearraysegment = NULL) mbytearraysegment = new bytearraysegment (tcputils. datapacketmaxlength); Return mbytearraysegment ;}}}}
The analyzer mainly overrides the readcast, writecast, and messageread methods, while the two cast methods mainly encapsulate a message as an adapter to an iMessage object for component processing. use the adapter messageadapter to realize the final object serialization and deserialization operations, and integrate the stream. with the above implementation, you can. net binary serialization objects are processed. The following Code creates a simple registration object.
[Serializable] public class register {Public String username {Get; set;} Public String email {Get; set;} public datetime responsetime {Get; set ;}}
Implement the corresponding TCP Service
After the protocol analyzer is expanded, it is used to implement a TCP interaction Service Based on Object serialization.
Class program: serverbase <binaryformatterpackage> {static void main (string [] ARGs) {tcputils. setup ("beetle"); program server = new program (); server. open( 9034); console. writeline ("service start @ 9034"); system. threading. thread. sleep (-1);} protected override void onconnected (Object sender, channeleventargs e) {base. onconnected (sender, e); console. writeline ("{0} connected! ", E. channel. endpoint);} protected override void ondisposed (Object sender, channeldisposedeventargs e) {base. ondisposed (sender, e); console. writeline ("{0} disposed! ", E. channel. endpoint);} protected override void onerror (Object sender, channelerroreventargs e) {base. onerror (sender, e); console. writeline ("{0} error {1 }! ", E. channel. endpoint, E. exception. message);} protected override void onmessagereceive (packetrecievemessagerargs e) {base. onmessagereceive (E); register = (Register) E. message; register. responsetime = datetime. now; E. channel. send (Register );}}
The implementation of the TCP Service is consistent with the original implementation method, but the generic parameters inherited from serverbase are protocol analyzer Types Based on Object serialization.
Connect to the service for object Communication
The code for accessing the server is just to change the generic parameter type.
Private void upload connect_click (Object sender, eventargs e) {try {channel = beetle. tcpserver. createclient <binaryformatterpackage> (txtipaddress. text, 9034, onreceive); channel. channeldisposed + = ondisposed; channel. channelerror + = onerror; channel. beginreceive (); cmdregister. enabled = true; Connect. enabled = false;} catch (exception E _) {MessageBox. show (E _. message) ;}} private void onreceive (B Eetle. packetrecievemessagerargs e) {register Reg = (Register) E. message; invoke (new action <register> (r => {txtremail. TEXT = R. email; txtrname. TEXT = R. username; txtresponsetime. TEXT = R. responsetime. tostring () ;}, REG) ;}private void ondisposed (Object sender, beetle. channeleventargs e) {invoke (new action <beetle. channeleventargs> (S => {txtstatus. TEXT = "disconnect! "; Cmdregister. enabled = false; Connect. enabled = true;}), e);} private void onerror (Object sender, beetle. channelerroreventargs e) {invoke (new action <beetle. channelerroreventargs> (r => {txtstatus. TEXT = R. exception. message;}), e );}
Send the object to the server
Register = new register (); register. Email = txtemail. Text; register. Username = txtname. Text; Channel. Send (Register );
Running Effect
Download Code: Code
Summary
The component provides flexible protocol extension functions, allowing you to transmit object information in different serialization modes simply by performing simple extension work. because. net binary serialization is a self-defined serialization method. If the interaction information with other platforms is not a good choice. the following section describes how to extend protobuf-net for object transmission.. NetBinary serialization has more advantages.