WebSocket C # server sends Big data, sub-packet Send Big Data method

Source: Internet
Author: User



See protocol

WebSocket data frame structure as shown: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-------+-+-------------+-------------------------------+ | F| r| r| r| opcode| m|    Payload Len |     Extended Payload Length | | i| s| s|  s| (4) |     a|             (7) |     (16/64) | | n| v| v|       v| |             s|   |     (if payload len==126/127) |       | |1|2|3| |             k|                               |     |     +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +     |     Extended payload length continued, if payload len = = 127 |                               + - - - - - - - - - - - - - - - +-------------------------------+     | |     Masking-key, if MASK set to 1 | +-------------------------------+-------------------------------+     |          Masking-key (continued) |     Payload Data | +-------------------------------- - - - - - - - - - - - - - - - +     :                     Payload Data continued: +-----------------------------------------                     - - - - - +     |     Payload Data Continued ... | +---------------------------------------------------------------+


Fin:1 bit
Indicates that this is the last frame of the message (the end frame), a message consisting of one or more data frames. If the message consists of a frame, the starting frame is the end frame.
Rsv1,rsv2,rsv3: each 1-bit
I do not translate well here, the general meaning is that if the extension is not defined, you are 0; If an extension is defined, it is a value other than 0. If the received frame is not 0, the extension does not have the definition of the value, then closes the connection.

Opcode:4 bit
Explanation Payloaddata, if an unknown opcode is received, the receiving end must close the connection.
0x0 indicates additional data frames
0x1 represents a text data frame
0x2 represents a binary data frame
0x3-7 temporarily undefined, reserved for future non-control frames
0x8 indicates the connection is closed
0x9 means ping
0xA represents Pong
0xb-f temporarily undefined, reserved for future control frames

Mask:1 bit
Used to identify whether the payloaddata is masked. If the data for the 1,masking-key domain is a masked key, it is used to decode the payloaddata. The data frame emitted by the client needs to be masked, so this bit is 1.

Payload length:7 bit, 7+16 bit, 7+64 bit payloaddata length in bytes. If its value is 0-125, it is the true length of the payload. If the value is 126, then the value of the 16-bit unsigned integer formed by the subsequent 2 bytes is the true length of the payload. Note that the network byte order needs to be converted. If the value is 127, then the value of the 64-bit unsigned integer formed by the subsequent 8 bytes is the true length of the payload. Note that the network byte order needs to be converted. Length means following a principle, with a minimum of bytes representing the length (I understand that it is possible to minimize unnecessary transmission). For example, the true length of the payload is 124, between 0-125, must be represented by the first 7 bits, the length 1 is 126 or 127, and the length 2 is 124, which violates the principle.
The above instructions are important. The following code is designed according to this principle


Payload length is the sum of extensiondata length and applicationdata length. The extensiondata length may be 0, in which case the payload length is applicationdata length.


The WebSocket protocol specifies that data is transmitted through a frame sequence.
The client must mask all the frames it sends to the server.
Once the server receives a mask-free frame, the connection is closed. The server may send a close frame with a status code of 1002 (which represents a protocol error).
While the server sends the client's data frame without mask processing, the connection is closed once the client discovers a masked frame. The client may use status code 1002.



message sharding


The purpose of the Shard is to send messages of unknown length. If you do not send a shard, that is, a frame, you need to cache the entire message, calculate its length, build frame and send; using shards, you can use a buffer of the right size, fill in buffer with the content of the message, and fill it out.


Shard rule:


1. One non-fragmented message only one frame (Fin is 1,opcode not 0)


2.the message for a shard consists of the starting frame (Fin is 0,opcode not 0), several (0 or more) frames (Fin is 0,opcode 0), and the end frame (Fin is 1,opcode 0).


3. The control frame can appear in the middle of the Shard message, but the control frame itself does not allow sharding.


4. Shard messages must be sent in order by frame.


5. If the extension is not negotiated, interleaving is not allowed between frames of two shard messages.


6. Ability to handle control frames that exist between fragmented message frames


7. Send end for non-control messages build arbitrary length of shards


8.client and server-compatible receive shard messages and non-shard messages


9. Control frame does not allow sharding, intermediate media does not allow to change the Shard structure (that is, to control the frame shard)


10. If a reserved bit is used, the intermediary does not know what the value represents, and the intermediary does not allow the change of the message's shard structure


11. If the intermediary media does not know if the extension is negotiated, then the intermediary media does not allow the change of the message's shard structure, and similarly, if the intermediary does not understand the information of a connected handshake, it does not allow the Shard structure of the message of the connection to be changed.


12. Because of the above rule, all shards of a message are data of the same data type (defined by the opcode of the first shard). Because control frames do not allow shards, the data type of all shards of a message is one of the text, binary, opcode reserved types.


It should be noted that if the control frame is not allowed to be mixed between the shards of a message, the delay will be large, for example, a large message is currently being transmitted, at which time the ping must wait for the message transmission to complete before it can be sent out, resulting in a large delay. To avoid similar problems, you need to allow the control frame inclusions between message shards.

Part of the Debug parsing message header code is as follows:

#if RFC6455 Debug Code #region Debug Code if (Receivebuffer.length > 2) {                        byte bt1 = receivebuffer[0];                        byte BT2 = receivebuffer[1];                        int Opcode = ((bt1 >> 4) & 0xF); Console.WriteLine (String. Format ("Fin:{0},rsv1:{1} rsv2:{2} rsv3:{3};opcode:{4},mask:{5};len:{6}", Bt1 >> 7 &                            1, (BT1 >> 6) & 1, (BT1 >> 5) & 1 , (BT1 >> 4) & 1, (BT1 & 0xF).                            ToString ("X2")///////second byte, BT2 >> 7 & 1//mask                        , Bt2 & 0x7f//payload len = = ((byte) (bt2<<1) >>1));                   The Fin:1 bit, which is used to indicate that this is the last message fragment of a message, and of course the first message fragment may also be the last message fragment     RSV1, RSV2, RSV3: are 1, respectively, if there is no agreement between the two sides of the custom protocol, then these values must be 0, otherwise you must break the WebSocket connection//opcode:4 bit opcode, define a valid negative                        Download data, if an unknown opcode is received, the connection must also be broken, the following is the defined opcode://*%x0 represents a continuous message fragment//*%x1 represents a fragment of a text message  *%X2 table not binary message fragment//*%x3-7 operation code reserved for future non-control message fragments//*%x8   Represents a connection close//*%x9 represents a heartbeat check of ping//*%xa indicates a heartbeat check Pong//* %xb-f the retention opcode for future control message fragments} #endregion #endif




The sending method code is as follows:

        <summary>///WebSocket send data to client, package server data///</summary>//<param NA Me= "bytes" > Data to be sent </param>//<param name= "Sendmax" > maximum packets per send </param> public void send        (byte[] Bytes,int sendmax=65536)            {bool Cansend = true;            Each time the maximum send 64Kb data int sendmax = Sendmax;            int num = 0;            BYTE data already sent int taked = 0;                while (cansend) {//Content data byte[] contentbytes = null; var Sendarr = bytes. Skip (num * sendmax). Take (Sendmax).                ToArray ();                taked + = Sendarr.length; if (Sendarr.length > 0) {//can continue sending Cansend = bytes.                    Length > taked; if (Sendarr.length < 126) {#region Send less than 126 data at a time conte Ntbytes = new Byte[sendarr.length + 2];                        Contentbytes[0] = (byte) (num = = 0? 0x81: (!cansend? 0x80:0));                        CONTENTBYTES[1] = (byte) sendarr.length;                        Array.copy (Sendarr, 0, Contentbytes, 2, sendarr.length);                        Cansend = false;                        #endregion} else if (Sendarr.length < 0xFFFF) {                        #region send data less than 65535 contentbytes = new Byte[sendarr.length + 4];                            First non-shard send, data greater than 128 bytes is sent out once if (!cansend && num = 0) {                        Contentbytes[0] = 0x81; } else {//a shard of messages from the starting frame (Fin is 0,opcode not 0), several (0 or more) frames                            (Fin is 0,opcode 0), end frame (Fin is 1,opcode 0).                        Contentbytes[0] = (byte) (num = = 0? 0x01: (!cansend? 0x80:0));} contentbytes[1] = 126;                        byte[] Ushortlen = Bitconverter.getbytes ((short) sendarr.length);                        CONTENTBYTES[2] = ushortlen[1];                        CONTENTBYTES[3] = ushortlen[0];                        Array.copy (Sendarr, 0, Contentbytes, 4, sendarr.length); #endregion} else if (Sendarr.longlength < long.                        MaxValue) {#region Send all data at once//long data once sent out                        Contentbytes = new Byte[sendarr.length + 10];                            First non-shard send, data greater than 128 bytes is sent out once if (!cansend && num = 0) {                        Contentbytes[0] = 0x81; } else {//a shard of messages from the starting frame (Fin is 0,opcode not 0), several (0 or more) frames                       (Fin is 0,opcode 0), end frame (Fin is 1,opcode 0).     Contentbytes[0] = (byte) (num = = 0? 0x01: (!cansend? 0x80:0));                        } Contentbytes[1] = 127;                        byte[] Ulonglen = Bitconverter.getbytes ((long) sendarr.length);                        CONTENTBYTES[2] = ulonglen[7];                        CONTENTBYTES[3] = ulonglen[6];                        CONTENTBYTES[4] = ulonglen[5];                        CONTENTBYTES[5] = ulonglen[4];                        CONTENTBYTES[6] = ulonglen[3];                        CONTENTBYTES[7] = ulonglen[2];                        CONTENTBYTES[8] = ulonglen[1];                        CONTENTBYTES[9] = ulonglen[0];                        Array.copy (Sendarr, 0, Contentbytes, ten, sendarr.length); #endregion}} try {if (contentbytes!                    = null) {socket.send (contentbytes);              }  } catch (NullReferenceException) {break;                } catch (System.Net.Sockets.SocketException) {break;                } catch (ObjectDisposedException) {break;                } finally {num++; }            }        }




WebSocket C # server sends Big data, sub-packet Send Big Data method

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.