C # enhanced version of udp for reliable transmission (packet group transmission)

Source: Internet
Author: User

In section c #, we discussed the reliable transmission of udp packets (packet group transmission). However, the problem with the previous program is that the data is relatively large, A Message class has 2048B after serialization, and the actual data volume is only 50B, which indicates that the data is very effective. In this way, when too many packets are transmitted, the efficiency will be greatly reduced. Therefore, we only need to find a way to reduce redundant data.

This notebook borrowed ideas from a FSLib. IPMessager project in the Flying Pigeon family and improved it. Thanks to the author of this project, I have a deep understanding of it.

We need to define our own data transmission structure. We can define a data header containing some basic necessary information, and then write the data to the end. I have posted this part of code. Please download the complete project in my resource area. I hope to share it with you because of the LZ originality!

Project

Using System; using System. Collections. Generic; using System. Linq; using System. Text; using System. Net; namespace Netframe. Model {////// Message encapsulation class ///Public class MessagePacker {/** Note: * 1. the first is always 2 (ASCII code 50) * 2. the second to ninth digits are a long integer representing the message number * 3. the tenth to 13th digits is an integer of the int type, representing the total length of the message content * 4. an integer of the int type ranging from 14th to 17th represents the total number of packages x 5. an integer of the int type ranging from 18th to 21st, representing the current subcontract number * 6. 22nd bits indicate whether to return a confirmation ID (1/0) * 7. 23rd to 31st bits are Reserved * 8. data Packet after 32nd bytes **/////// Message version number ///Public static byte VersionHeader {get {return 50 ;}}////// Return the header bytes of the current message packet ///Public static int PackageHeaderLength {get {return 32 ;}}////// Obtain the byte stream of the message package //////Message object to be packaged///
 Public static UdpPacketMsg [] BuildNetworkMessage (Msg message) {if (message. ExtendMessageBytes! = Null) {return BuildNetworkMessage (message. remoteAddr, message. packageNo, message. command, message. userName, message. hostName, message. type, message. normalMsgBytes, message. extendMessageBytes, message. isRequireReceive);} else {return BuildNetworkMessage (message. remoteAddr, message. packageNo, message. command, message. userName, message. hostName, message. type, System. text. encoding. unicode. getBytes (message. normalMsg), System. text. encoding. unicode. getBytes (message. extendMessage), message. isRequireReceive );}}////// Obtain the byte stream of the message package //////Remote Host address///Package ID///Command///Parameters///User Name///Host Name///Body message///Extended messages///
 Public static UdpPacketMsg [] BuildNetworkMessage (IPEndPoint remoteIp, long packageNo, Commands command, string userName, string hostName, Consts type, byte [] content, byte [] extendContents, bool RequireReceiveCheck) {// The amount of data that can be stored in each send. int maxBytesPerPackage = (int) Consts. MAX_UDP_PACKAGE_LENGTH-PackageHeaderLength; // compresses the data stream System. IO. memoryStream MS = new System. IO. memoryStream (); System. IO. compressio N. GZipStream zip = new System. IO. compression. GZipStream (MS, System. IO. compression. compressionMode. compress); System. IO. binaryWriter bw = new System. IO. binaryWriter (zip, System. text. encoding. unicode); // write the header data bw. write (packageNo); // Package number bw. write (userName); // userName bw. write (hostName); // host name bw. write (long) command); // command bw. write (long) type); // data type bw. write (content = null? 0: content. Length); // Data Length // write message data if (content! = Null) bw. Write (content); bw. Write (extendContents = null? 0: extendContents. Length); // supplement the data Length if (extendContents! = Null) bw. write (extendContents); // bw. close (); // zip. close (); ms. flush (); ms. seek (0, System. IO. seekOrigin. begin); // total volume of packaged data int dataLength = (int) ms. length; int packageCount = (int) Math. ceiling (dataLength * 1.0/maxBytesPerPackage); UdpPacketMsg [] pnma = new UdpPacketMsg [packageCount]; for (int I = 0; I <packageCount; I ++) {int count = I = packageCount-1? DataLength-maxBytesPerPackage * (packageCount-1): maxBytesPerPackage; byte [] buf = new byte [count + PackageHeaderLength]; buf [0] = VersionHeader; // BitConverter with version 1st characters. getBytes (packageNo ). copyTo (buf, 1); // The BitConverter message number ranges from 2nd to 9-bit long. getBytes (dataLength ). copyTo (buf, 9); // The length of the message content is 10th to 13-bit integer BitConverter of the int type. getBytes (packageCount ). copyTo (buf, 13); // BitConverter, an integer of the int type ranging from 14th to 17th bits in total. get Bytes (I). CopyTo (buf, 17); // buf [21] = RequireReceiveCheck? (Byte) 1: (byte) 0; // check whether the 22nd bits/23rd to 31st bits are Reserved ms. read (buf, 32, buf. length-32); // After 32nd bytes, the specific Data packet pnma [I] = new UdpPacketMsg () {Data = buf, PackageCount = packageCount, PackageIndex = I, packageNo = packageNo, RemoteIP = remoteIp, SendTimes = 0, Version = 2, IsRequireReceiveCheck = buf [21] = 1};} bw. close (); zip. close (); ms. close (); return pnma ;}////// Check whether the message package is of this type /////////
 Public static bool Test (byte [] buffer) {return buffer! = Null & buffer. Length> PackageHeaderLength & buffer [0] = VersionHeader ;}////// Cache the received fragment ///Static Dictionary
 
  
PackageCache = new Dictionary
  
   
();///
   /// Analyze network data packets and convert them to Information Objects //////
   Received packet object///
   ///
   
    
/// For packet forwarding, if only the segment is received and the packet is not completely received, the packet will not be parsed ///
   Public static Msg ParseToMessage (params UdpPacketMsg [] packs) {if (packs. Length = 0 | (packs [0]. PackageCount> 1 & packs. Length! = Packs [0]. packageCount) return null; // try to extract, sort Array first. sort (packs); // try to decompress System. IO. memoryStream MS = new System. IO. memoryStream (); System. IO. compression. GZipStream zip = new System. IO. compression. GZipStream (MS, System. IO. compression. compressionMode. decompress); // System. IO. binaryWriter bw = new System. IO. binaryWriter (zip, System. text. encoding. unicode); try {foreach (var s in packs) {if (zip. canWrite) {zip. write (s. data, 0, s. data. length) ;}// Array. forEach (packs, s => zip. write (s. data, 0, s. data. length);} catch (Exception e) {// trigger event return null;} zip. close (); ms. flush (); ms. seek (0, System. IO. seekOrigin. begin); // construct the read stream System. IO. binaryReader br = new System. IO. binaryReader (MS, System. text. encoding. unicode); // start to read data Msg m = new Msg (packs [0]. remoteIP); m. packageNo = br. readInt64 (); // Package number m. userName = br. readString (); // username m. hostName = br. readString (); // host name m. command = (Commands) br. readInt64 (); // command m. type = (Consts) br. readInt64 (); // data type int length = br. readInt32 (); // data length m. normalMsgBytes = new byte [length]; br. read (m. normalMsgBytes, 0, length); // read content length = br. readInt32 (); // additional data length m. extendMessageBytes = new byte [length]; br. read (m. extendMessageBytes, 0, length); // read additional data if (m. type = Consts. MESSAGE_TEXT) {m. normalMsg = System. text. encoding. unicode. getString (m. normalMsgBytes, 0, length); // body m. extendMessage = System. text. encoding. unicode. getString (m. extendMessageBytes, 0, length); // extended message m. extendMessageBytes = null; m. normalMsgBytes = null;} return m ;}///
   /// Try to resolve the received network package to an object //////
   Received Network Package///
   ///
   
    
If the received package is a multipart package and all its sub-packages are not completely accepted, a null value is returned.
   Public static Msg TryToTranslateMessage (UdpPacketMsg pack) {if (pack = null | pack. packageIndex> = pack. packageCount-1) return null; else if (pack. packageCount = 1) return ParseToMessage (pack); else {if (packageCache. containsKey (pack. packageNo) {UdpPacketMsg [] array = packageCache [pack. packageNo]; array [pack. packageIndex] = pack; // check whether the if (Array. findIndex (array, s => s = null) =-1) {packageCache. remove (pack. packageNo); return ParseToMessage (array);} else {return null ;}} else {UdpPacketMsg [] array = new UdpPacketMsg [pack. packageCount]; array [pack. packageIndex] = pack; packageCache. add (pack. packageNo, array); return null ;}}}///
   /// Resolve the network information to a packet //////
   ///
   Public static UdpPacketMsg Parse (byte [] buffer, IPEndPoint clientAddress) {if (! Test (buffer) return null; UdpPacketMsg p = new UdpPacketMsg () {RemoteIP = clientAddress, SendTimes = 0}; p. packageNo = BitConverter. toInt64 (buffer, 1); // package No. p. dataLength = (int) BitConverter. toInt64 (buffer, 9); // Content Length p. packageCount = BitConverter. toInt32 (buffer, 17); // Total number of packages p. packageIndex = BitConverter. toInt32 (buffer, 21); // index p. isRequireReceiveCheck = buffer [21] = 1; // whether to return packets p. data = new byte [buffer. length-PackageHeaderLength]; Array. copy (buffer, PackageHeaderLength, p. data, 0, p. data. length); return p ;}}}
  
 


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.