Assume that the message header is 16byte0-3 message header ID 4-7 message body length 8-15 CRC verification code
Public class streamhelper {# region converts a message into a byte array containing the message header /// <summary> /// converts the message into a byte array containing the message header /// </Summary> /// <Param name = "stream"> </param> /// <Param name = "message"> </param> /// <returns> </returns> public static byte [] getwrappedmessage (Google. protocolbuffers. iMessage message) {byte [] buff = message. tobytearray (); CRC32 CRC32 = new CRC32 (); crc32.update (buff); memorystream MS = new memorystream (); BYT E [] Tag = bitconverter. getbytes (constants. tag); byte [] Len = bitconverter. getbytes (buff. length); byte [] CRC = bitconverter. getbytes (crc32.value); Ms. write (TAG, 0, Tag. length); // write the header Ms. write (Len, 0, Len. length); // write the message length in ms. write (CRC, 0, CRC. length); // write the CRC32 value Ms. write (buff, 0, Buff. length); byte [] result = Ms. toarray (); Ms. close (); return result ;}# endregion # region writes the message to the stream // <summary> /// Write a message to a stream /// </Summary> /// <Param name = "stream"> </param> /// <returns> </returns> Public static void writetostream (networkstream stream, google. protocolbuffers. iMessage message) {byte [] buff = message. tobytearray (); CRC32 CRC32 = new CRC32 (); crc32.update (buff); byte [] Tag = bitconverter. getbytes (constants. tag); byte [] Len = bitconverter. getbytes (buff. length); byte [] CRC = bitconverter. getbytes (Cr C32.value); stream. write (TAG, 0, Tag. length); // write the header stream. write (Len, 0, Len. length); // write the message length stream. write (CRC, 0, CRC. length); // write the CRC32 Value Stream. write (buff, 0, Buff. length );} # endregion # region writes a message to socket /// <summary> /// write the message to socket /// </Summary> /// <Param name = "socket"> </param> // <returns> </returns> Public static void writetosocket (Socket socket, google. protocolbuffers. iMessage mess Age) {byte [] buff = message. tobytearray (); CRC32 CRC32 = new CRC32 (); crc32.update (buff); byte [] Tag = bitconverter. getbytes (constants. tag); byte [] Len = bitconverter. getbytes (buff. length); byte [] CRC = bitconverter. getbytes (crc32.value); socket. sendbuffersize = constants. headsize + buff. length; socket. send (TAG); // write the header socket. send (LEN); // write the message length socket. send (CRC); // write the CRC32 value socket. send (buff );} # Endregion # region reads all bytes from networkstream /// <summary> /// reads all bytes from networkstream /// </Summary> /// <Param name = "stream "> </param> // <returns> </returns> Public static byte [] readallbytes (networkstream Stream) {byte [] Head = new byte [constants. headsize]; If (stream. read (Head, 0, constants. headsize )! = Constants. headsize) // The transmission header is 16 bits. Only {return NULL;} headinfo = new headinfo (head); If (headinfo. Tag! = Constants. tag) // incorrect header {return NULL;} byte [] buff = new byte [headinfo. len]; int size = math. min (buff. length, 4096); // The maximum number of bytes read at a time. Int offset = 0; do {size = math. min (size, headinfo. len-offset); offset + = stream. read (buff, offset, size); If (offset = headinfo. len) // receives the specified length {CRC32 CRC32 = new CRC32 (); crc32.update (buff); If (crc32.value = headinfo. crc32value) // verify CRC32 {return Buff; }}} While (stream. dataavailable); log. errorformat ("client request failed: Offset {0}, head Len {1}", offset, headinfo. len); return NULL ;} # endregion # region reads all bytes from the socket /// <summary> /// reads all bytes from the socket /// </Summary> /// <Param name = "socket"> </param> /// <returns> </returns> Public static byte [] readallbytes (Socket socket) {byte [] Head = new byte [constants. headsize]; byte [] result = NULL; socketerror Error = Socketerror. success; int maxrepeat = 5; int got = 0; int repeat = 0; do // read the header {got ++ = socket. receive (Head, got, constants. headsize-got, socketflags. none, out error); If (got = constants. headsize | repeat> maxrepeat) // if the request is received completely or repeatedly for 10 times, {break;} else if (got = 0) // The number of times the Data repeat cannot be obtained {+ + repeat;} while (error = socketerror. success); If (got! = Constants. headsize) // verify the header length {log. error ("Incorrect head length"); return NULL;} headinfo = new headinfo (head); If (headinfo. tag! = Constants. tag) // the header is incorrect {log. errorformat ("head. tag incorrect ({0}, actual {1}) ", constants. tag, headinfo. tag); return NULL;} result = new byte [headinfo. len]; repeat = 0; got = 0; do // read the message body {got + = socket. receive (result, got, result. length-got, socketflags. none, out error); If (got = result. length | repeat> maxrepeat) // The {break;} else if (got = 0) is still not received if it has been received completely or repeated for 10 times) // The number of times the Data repeat cannot be obtained {+ + repeat ;}} While (error = socketerror. Success); If (got! = Result. length) // verification length {log. errorformat ("the length is incorrect ({0}, actually {1})", result. length, got); return NULL;} CRC32 CRC32 = new CRC32 (); crc32.update (result); If (crc32.value! = Headinfo. crc32value) // verify CRC32 {log. errorformat ("CRC verification failed ({0}, actual {1})", headinfo. crc32value, crc32.value); return NULL;} return result ;}# endregion # region asynchronously receives socket data (for testing) /// <summary> /// asynchronously receives socket data /// </Summary> /// <Param name = "socket"> </param> /// <returns> </returns> Public static byte [] receivedata (Socket socket) {receiveobject state = new receiveobject () {client = socket}; SOC Ket. beginreceive (state. buffer, 0, state. buffer. length, socketflags. none, new asynccallback (readcallback), State); State. receivedone. waitone (socket. receivetimeout); // timeout setting byte [] Head = new byte [constants. headsize]; State. stream. seek (0, seekorigin. begin); If (state. stream. read (Head, 0, constants. headsize )! = Constants. headsize) // read the header {return NULL;} headinfo = new headinfo (head); If (headinfo. Tag! = Constants. Tag) // the header is incorrect {return NULL;} If (State. Stream. Length-16! = Headinfo. len) // verification length {return NULL;} // state. stream. seek (16, seekorigin. begin); byte [] result = new byte [State. stream. length-16]; State. stream. read (result, 0, result. length); // read the message body CRC32 CRC32 = new CRC32 (); crc32.update (result); If (crc32.value = headinfo. crc32value) // verify CRC32 {return result;} return NULL;} // <summary> // synchronously receives the object // </Summary> private class receiveobject: idisposable {public Socket Client; Public byte [] buffer = new byte [4096]; public system. io. memorystream stream = new system. io. memorystream (); public system. threading. manualresetevent receivedone = new system. threading. manualresetevent (false); Public void dispose () {This. stream. close ();}} /// <summary> /// read callback /// </Summary> /// <Param name = "Ar"> </param> Private Static void readcallback (iasyncresult ar) {receiveobject state = (receiveobject) ar. asyncstate; int bytesread = state. client. endreceive (AR); If (bytesread> 0) {try {state. stream. write (state. buffer, 0, bytesread); State. client. beginreceive (state. buffer, 0, state. buffer. length, socketflags. none, new asynccallback (readcallback), State);} catch (exception ex) {log. error (ex. message); State. receivedone. set () ;}} else {state. receivedone. set (); // state. client. endreceive (AR) ;}# endregion}