ArticleDirectory
- First, develop a TCP Service
- Flash implementation
Previous articles have introduced how beetle uses protobuf.net for Object serialization data transmission. This chapter describes how beetle uses fluorinefx and flash for amf3 communication. the implementation principle is the same as that of protobuf.net. You can extend a messageadapter.
The implementation of messageadapter is as follows:
Public class messageadapter: iMessage {public object message {Get; set;} public static bool send (tcpchannel channel, object message) {messageadapter MA = new messageadapter (); MA. message = message; return channel. send (MA);} public void load (bufferreader reader) {bytearraysegment segment = arraypool. pop (); int COUNT = reader. readint32 (); reader. read (count-4, segment); Using (system. io. memorystream steram = new system. io. memorystream (segment. array, segment. offset, segment. count) {fluorinefx. amf3.bytearray BA = new fluorinefx. amf3.bytearray (steram); BA. objectencoding = fluorinefx. objectencoding. amf3; message = BA. readobject ();} arraypool. push (segment);} public void save (bufferwriter writer) {bytearraysegment segment = arraypool. pop (); Using (system. io. memorystream steram = new system. io. memorystream (segment. array) {fluorinefx. amf3.bytearray BA = new fluorinefx. amf3.bytearray (steram); BA. objectencoding = fluorinefx. objectencoding. amf3; BA. writeobject (Message); segment. setinfo (0, (INT) steram. position);} writer. write (segment. count + 4); writer. write (segment. array, segment. offset, segment. count); arraypool. push (segment);} public static bytearraypool arraypool = new bytearraypool (200,102 4*8 );}
The implementation of the message adapter is relatively simple. when an object is written into a stream, amf3 serializes the length of the object stream + 4 into the first 4 bytes, and then writes the data stream content of amf3, reading objects from a stream is the same as reading the message length first, then reading the amf3 data stream and deserializing the object.
Implements a protocol analyzer that describes the length of a message header:
Public class headsizepackage: bytes {public headsizepackage () {} public headsizepackage (tcpchannel channel): Base (Channel) {} protected override iMessage readmessagebytype (bufferreader reader, out object pettyag) {typetag = "messageadapter"; return New messageadapter ();} protected override void writemessagetype (iMessage MSG, bufferwriter writer) {} public override void messagewrite (iMessage MSG, bufferwriter writer) {MSG. save (writer);} 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 ;}}
The Protocol format generated by such a message extension is as follows:
After the protocol is developed, you can use beetle to build amf3-based. NET and flash data transmission.
First, develop a TCP Service
Tcputils. Setup (200, 1, 1); tcpserver Server = new tcpserver (); server. channelconnected + = onconnected; server. channeldisposed + = ondisposed; server. Open (8340 );
AboveCodeIt is easy to initialize the component information, build a tcpserver, bind a connection access event and a connection disconnection event, and then bind the TCP Service on the 8340 side of all IP addresses. We need to do something during connection access.
Static void onconnected (Object sender, channeleventargs e) {e. channel. setpackage <beetle. fluorinefxadapter. headsizepackag> (). receivemessage = onmessagereceive; E. channel. channelerror + = onerror; E. channel. beginreceive (); console. writeline ("{0} connected! ", E. Channel. endpoint );}
Set a protocol subcontractor for the current TCP channel in the access event and specify the corresponding message receiving event. After the TCP channel information is set, you can call beginreceive () method to enter the data receiving status. The following is the Message Processing Event code:
Static void onmessagereceive (packetrecievemessagerargs e) {beetle. fluorinefxadapter. messageadapter adapter = (beetle. fluorinefxadapter. messageadapter) E. message; If (adapter. message is amf3.messages. register) {onregister (amf3.messages. register) adapter. message, E. channel);} else if (adapter. message is amf3.messages. get) {onget (amf3.messages. get) adapter. message, E. channel);} else {}} static void onregister (amf3.messages. register E, tcpchannel channel) {console. writeline ("{0} register \ t Username: {1}; PWD: {2}; email: {3}", channel. endpoint, E. username, E. PWD, E. email);} static void onget (amf3.messages. get E, tcpchannel channel) {console. writeline ("{0} Get \ t Customer: {1}", channel. endpoint, E. customerid); amf3.messages. getresponse response = new messages. getresponse (); For (INT I = 0; I <10; I ++) {amf3.messages. order order = new messages. order (); Order. orderid = 10248; Order. customerid = "wilmk"; Order. employeeid = 5; Order. orderdate = 629720352000000000; Order. requireddate = 629744544000000000; Order. shipaddress = "59 Rue de l 'abbaye"; Order. shipcity = "Reims"; Order. shipcountry = "France"; Order. shipname = "Vins et alcools chevalier"; Order. shippostalcodes = "51100"; Order. shipregion = "RJ"; response. items. add (order);} beetle. fluorinefxadapter. messageadapter. send (Channel, response );}
In this example, only two types of message objects are processed: Register and get. Only a simple output is made to the received register, and an order list is returned when get is received.
Flash implementation
First of all, we need to implement the Protocol subcontractor. Because the socket method provided by Flash is quite convenient, it is also very easy to implement.
Package {import flash.net. socket; import flash. utils. bytearray; import flash. utils. endian; import MX. graphics. shaderclasses. exclusionshader; public class headsizeofpackage {public function headsizeofpackage () {} private var mmessagereceive: function; // message receiving callback function public function get messagereceive (): function {return response ;} public Function set messagereceive (value: function): void {mmessagereceive = value;} Private var mreader: bytearray = new bytearray (); Private var mwriter: bytearray = new bytearray (); Private var msize: Int = 0; // import the data received by the current socket Public Function Import (socket: socket): void {socket. endian = endian. little_endian; while (socket. bytesavailable> 0) {If (msize = 0) {msize = socket. readint ()-4; mreader. clear ();} If (socket. bytesavailable> = msize) {socket. readbytes (mreader, mreader. length, msize); var MSG: Object = Mreader. readobject (); If (messagereceive! = NULL) messagereceive (MSG); msize = 0;} else {msize = mSize-socket.bytesAvailable; socket. readbytes (mreader, mreader. length, socket. bytesavailable) ;}}// protocol data encapsulated in payload public function send (message: object, socket: socket): void {socket. endian = endian. little_endian; mwriter. clear (); mwriter. writeobject (Message); socket. writeint (mwriter. length + 4); socket. writebytes (mwriter, 0, mwriter. length); socket. flush ();}}}
If the data size to be read is zero, it indicates a new message. In this case, read the message size first. Note that C # is a low-order message, beetle implementation is not processed either. therefore, we need to set the flash socket to low-order processing. after reading a complete amf3 data stream, you can directly read the relevant object and use function callback. in the same way as sending a message, write the total length of the message first and then write the corresponding amf3 data stream. this way, a flash package and package are completed, and the following can be accessed. NET Server for data interaction.
Private var mpackage: headsizeofpackage = new headsizeofpackage (); protected function connectconnect_clickhandler (Event: mouseevent): void {// todo auto-generated method stubmsocket = new socket (); msocket. connect (txtipaddress. text, 9860); msocket. addeventlistener (event. connect, onconnected); msocket. addeventlistener (progressevent. socket_data, socketdatahandler); msocket. endian = endian. little_endian; mpackage. messagereceive = onreceive;} private function onreceive (MSG: Object): void {If (MSG is getresponse) {var response: getresponse = getresponse (MSG); lstdata. dataprovider = new arraycollection (response. items) ;}} private function socketdatahandler (Event: progressevent): void {trace ("socketdatahandler:" + Event); mpackage. import (msocket);} private function onconnected (Event: Event): void {cmdregister. enabled = true; enabled get. enabled = true;} protected function cmdregister_clickhandler (Event: mouseevent): void {// todo auto-generated method stubvar REG: Register = new register (); Reg. email = txtemail. text; Reg. username = txtusername. text; Reg. pwd = txtpwd. text; mpackage. send (Reg, msocket);} protected function initialize get_clickhandler (Event: mouseevent): void {// todo auto-generated method stubvar get: Get = new get (); get. customerid = txtcustomerid. text; mpackage. send (get, msocket );}
Specific Running Effect
Download related Code