मैं सर्वर साइड पर WebSocket संदेश कैसे भेज और प्राप्त कर सकता हूं?


85
  • मैं प्रोटोकॉल के अनुसार, WebSocket का उपयोग करके सर्वर साइड पर संदेश कैसे भेज और प्राप्त कर सकता हूं?

  • जब मैं ब्राउज़र से सर्वर पर डेटा भेजता हूं तो मुझे सर्वर पर प्रतीत होने वाले यादृच्छिक बाइट्स क्यों मिलते हैं? यह डेटा किसी तरह एन्कोड किया गया?

  • सर्वर → क्लाइंट और क्लाइंट → सर्वर निर्देशों दोनों में फ्रेमिंग कैसे काम करता है?

जवाबों:


154

नोट: यह कुछ स्पष्टीकरण और छद्म कोड के रूप में है कि कैसे एक बहुत ही तुच्छ सर्वर को लागू किया जाए जो निश्चित फ़्रेमिंग प्रारूप के अनुसार आने वाले और बाहर आने वाले वेबसैट संदेशों को संभाल सकता है। इसमें हैंडशेकिंग प्रक्रिया शामिल नहीं है। इसके अलावा, यह जवाब शैक्षिक उद्देश्यों के लिए बनाया गया है; यह पूर्ण विशेषताओं वाला कार्यान्वयन नहीं है।

विशिष्टता (RFC 6455)


संदेश भेजना

(दूसरे शब्दों में, सर्वर → ब्राउज़र)

वे फ़्रेम जिन्हें आप भेज रहे हैं, उन्हें WebSocket फ़्रेमिंग प्रारूप के अनुसार स्वरूपित करने की आवश्यकता है। संदेश भेजने के लिए, यह प्रारूप इस प्रकार है:

  • एक बाइट जिसमें डेटा का प्रकार होता है (और कुछ अतिरिक्त जानकारी जो एक तुच्छ सर्वर के दायरे से बाहर है)
  • एक बाइट जिसमें लंबाई होती है
  • या तो दो या आठ बाइट्स यदि लंबाई दूसरी बाइट में फिट नहीं होती है (दूसरी बाइट तब एक कोड है जिसमें कहा जाता है कि लंबाई के लिए कितने बाइट्स का उपयोग किया जाता है)
  • वास्तविक (कच्चा) डेटा

पहला बाइट एक टेक्स्ट फ़्रेम के लिए 1000 0001(या 129) होगा ।

दूसरे बाइट का पहला सेट है 0क्योंकि हम डेटा को एन्कोडिंग नहीं कर रहे हैं (सर्वर से क्लाइंट के लिए एन्कोडिंग अनिवार्य नहीं है)।

कच्चे डेटा की लंबाई निर्धारित करना आवश्यक है ताकि लंबाई बाइट्स को सही ढंग से भेजा जा सके:

  • यदि 0 <= length <= 125, आपको अतिरिक्त बाइट्स की आवश्यकता नहीं है
  • यदि 126 <= length <= 65535, आपको दो अतिरिक्त बाइट्स की आवश्यकता है और दूसरा बाइट है126
  • यदि length >= 65536, आपको आठ अतिरिक्त बाइट्स की आवश्यकता है, और दूसरी बाइट है127

लंबाई को अलग-अलग बाइट्स में कटा हुआ होना चाहिए, जिसका अर्थ है कि आपको दाईं ओर (आठ बिट्स की राशि के साथ) बिट-शिफ्ट करने की आवश्यकता होगी, और फिर केवल AND 1111 1111(जो है 255) करके पिछले आठ बिट्स को बनाए रखें ।

लंबाई बाइट के बाद कच्चा डेटा आता है।

यह निम्नलिखित छद्मकोश की ओर जाता है:

bytesFormatted[0] = 129

indexStartRawData = -1 // it doesn't matter what value is
                       // set here - it will be set now:

if bytesRaw.length <= 125
    bytesFormatted[1] = bytesRaw.length

    indexStartRawData = 2

else if bytesRaw.length >= 126 and bytesRaw.length <= 65535
    bytesFormatted[1] = 126
    bytesFormatted[2] = ( bytesRaw.length >> 8 ) AND 255
    bytesFormatted[3] = ( bytesRaw.length      ) AND 255

    indexStartRawData = 4

else
    bytesFormatted[1] = 127
    bytesFormatted[2] = ( bytesRaw.length >> 56 ) AND 255
    bytesFormatted[3] = ( bytesRaw.length >> 48 ) AND 255
    bytesFormatted[4] = ( bytesRaw.length >> 40 ) AND 255
    bytesFormatted[5] = ( bytesRaw.length >> 32 ) AND 255
    bytesFormatted[6] = ( bytesRaw.length >> 24 ) AND 255
    bytesFormatted[7] = ( bytesRaw.length >> 16 ) AND 255
    bytesFormatted[8] = ( bytesRaw.length >>  8 ) AND 255
    bytesFormatted[9] = ( bytesRaw.length       ) AND 255

    indexStartRawData = 10

// put raw data at the correct index
bytesFormatted.put(bytesRaw, indexStartRawData)


// now send bytesFormatted (e.g. write it to the socket stream)

संदेश प्राप्त करना

(दूसरे शब्दों में, ब्राउज़र → सर्वर)

आपके द्वारा प्राप्त फ़्रेम निम्नलिखित प्रारूप में हैं:

  • एक बाइट जिसमें डेटा का प्रकार होता है
  • एक बाइट जिसमें लंबाई होती है
  • यदि दो या आठ अतिरिक्त बाइट्स हैं, तो लंबाई दूसरी बाइट में फिट नहीं होती है
  • चार बाइट्स जो मास्क हैं (= डिकोडिंग कीज़)
  • वास्तविक डेटा

पहला बाइट आमतौर पर मायने नहीं रखता है - यदि आप केवल पाठ भेज रहे हैं तो आप केवल पाठ प्रकार का उपयोग कर रहे हैं। यह उस मामले में 1000 0001(या 129) होगा ।

दूसरे बाइट और अतिरिक्त दो या आठ बाइट्स को कुछ पार्सिंग की आवश्यकता होती है, क्योंकि आपको यह जानने की आवश्यकता है कि लंबाई के लिए कितने बाइट्स का उपयोग किया जाता है (आपको यह जानना होगा कि वास्तविक डेटा कहाँ शुरू होता है)। आपके पास डेटा पहले से ही लंबाई आमतौर पर आवश्यक नहीं है।

दूसरी बाइट का पहला बिट हमेशा होता है 1जिसका अर्थ है कि डेटा नकाब (= एन्कोडेड) है। क्लाइंट से सर्वर तक संदेश हमेशा नकाबपोश होते हैं। आपको उस पहले बिट को हटाने की आवश्यकता है secondByte AND 0111 1111। ऐसे दो मामले हैं जिनमें परिणामी बाइट लंबाई का प्रतिनिधित्व नहीं करती है क्योंकि यह दूसरी बाइट में फिट नहीं होती है:

  • की दूसरी बाइट 0111 1110, या 126, का अर्थ है कि निम्नलिखित दो बाइट्स लंबाई के लिए उपयोग किए जाते हैं
  • की एक दूसरी बाइट 0111 1111, या 127, इसका मतलब है कि लंबाई के लिए निम्नलिखित आठ बाइट्स का उपयोग किया जाता है

चार मास्क बाइट्स का उपयोग वास्तविक डेटा को डिकोड करने के लिए किया जाता है जिसे भेजा गया है। डिकोडिंग के लिए एल्गोरिथ्म इस प्रकार है:

decodedByte = encodedByte XOR masks[encodedByteIndex MOD 4]

जहां encodedByteडेटा में मूल बाइट है, वास्तविक डेटाencodedByteIndex के पहले बाइट से बाइट काउंटिंग का सूचकांक (ऑफसेट) है , जिसमें इंडेक्स है । चार मुखौटा बाइट्स से युक्त एक सरणी है।0masks

यह डिकोडिंग के लिए निम्नलिखित छद्मकोश की ओर जाता है:

secondByte = bytes[1]

length = secondByte AND 127 // may not be the actual length in the two special cases

indexFirstMask = 2          // if not a special case

if length == 126            // if a special case, change indexFirstMask
    indexFirstMask = 4

else if length == 127       // ditto
    indexFirstMask = 10

masks = bytes.slice(indexFirstMask, 4) // four bytes starting from indexFirstMask

indexFirstDataByte = indexFirstMask + 4 // four bytes further

decoded = new array

decoded.length = bytes.length - indexFirstDataByte // length of real data

for i = indexFirstDataByte, j = 0; i < bytes.length; i++, j++
    decoded[j] = bytes[i] XOR masks[j MOD 4]


// now use "decoded" to interpret the received data

1000 0001टेक्स्ट फ्रेम के लिए क्यों (129)? युक्ति कहती है %x1 denotes a text frame:। तो यह होना चाहिए 0000 0001( 0x01), या?
डेनिस

3
@ डेनिस: फ़्रेम ओपकोड है 0001, क्योंकि यह ऐनक के उस हिस्से के हेडर पर बताता है: "ओपकोड: 4 बिट्स"। पहले बाइट में फिन, RSV1-3 और ओपकोड शामिल हैं। फिन है 1, RSV1-3 तीनों हैं 0और पहली बार बाइट के लिए ओपकोड 0001जोड़ा गया है 1000 0001। विनिर्देश में कलाकृति भी देखें जो प्रदर्शित करता है कि बाइट्स को अलग-अलग हिस्सों में कैसे विभाजित किया गया है।
पीमवेदब

आपके पास कुछ पंक्तियाँ हैं जो 'bytesFormatted [2] = (bytesRaw.length >> 56) और 255' जैसे सर्वर-> क्लाइंट मॉडल में पढ़ी जाती हैं - क्या आप मेरे लिए ऐसा करना चाहेंगे? और मेरे लिए एक तार्किक ऑपरेटर लगता है इसलिए मुझे उम्मीद है कि सी # में मेरे लिए कुछ भी करने के बाद बस एक नंबर डालना होगा। इसी तरह, मुझे यकीन नहीं है कि आपके मार्कअप में ">>" क्या संकेत करता है - हालांकि यह C # पर ट्रांसफर करता है ... जो भी मेरे लिए इसका मतलब है ...: P
DigitalJedi805

अगर कोई वास्तव में मेरे लिए यह स्पष्ट कर सकता है, तो मुझे उत्तर के रूप में अपना सी # कार्यान्वयन पोस्ट करने में खुशी होगी।
DigitalJedi805

1
@ नीवेक: उनका क्या मतलब है कि मास्क बाइट्स को अप्रत्याशित होने की आवश्यकता है। अगर वे स्थिर हैं तो उनमें बहुत ज्यादा जगह नहीं है। मूल रूप से, जब एक दुर्भावनापूर्ण उपयोगकर्ता के पास डेटा का एक टुकड़ा होता है, तो उसे मास्क के बिना डिकोड करने में सक्षम नहीं होना चाहिए। यदि मास्क की स्थिति अनुमानित नहीं है, तो वास्तविक सर्वर को डिकोड करना थोड़ा मुश्किल है :)
pimvdb

26

जावा कार्यान्वयन (यदि किसी की आवश्यकता है)

रीडिंग: क्लाइंट टू सर्वर

        int len = 0;            
        byte[] b = new byte[buffLenth];
        //rawIn is a Socket.getInputStream();
        while(true){
            len = rawIn.read(b);
            if(len!=-1){

                byte rLength = 0;
                int rMaskIndex = 2;
                int rDataStart = 0;
                //b[0] is always text in my case so no need to check;
                byte data = b[1];
                byte op = (byte) 127;
                rLength = (byte) (data & op);

                if(rLength==(byte)126) rMaskIndex=4;
                if(rLength==(byte)127) rMaskIndex=10;

                byte[] masks = new byte[4];

                int j=0;
                int i=0;
                for(i=rMaskIndex;i<(rMaskIndex+4);i++){
                    masks[j] = b[i];
                    j++;
                }

                rDataStart = rMaskIndex + 4;

                int messLen = len - rDataStart;

                byte[] message = new byte[messLen];

                for(i=rDataStart, j=0; i<len; i++, j++){
                    message[j] = (byte) (b[i] ^ masks[j % 4]);
                }

                parseMessage(new String(message)); 
                //parseMessage(new String(b));

                b = new byte[buffLenth];

            }
        }

लेखन: सर्वर से क्लाइंट

public void brodcast(String mess) throws IOException{
    byte[] rawData = mess.getBytes();

    int frameCount  = 0;
    byte[] frame = new byte[10];

    frame[0] = (byte) 129;

    if(rawData.length <= 125){
        frame[1] = (byte) rawData.length;
        frameCount = 2;
    }else if(rawData.length >= 126 && rawData.length <= 65535){
        frame[1] = (byte) 126;
        int len = rawData.length;
        frame[2] = (byte)((len >> 8 ) & (byte)255);
        frame[3] = (byte)(len & (byte)255); 
        frameCount = 4;
    }else{
        frame[1] = (byte) 127;
        int len = rawData.length;
        frame[2] = (byte)((len >> 56 ) & (byte)255);
        frame[3] = (byte)((len >> 48 ) & (byte)255);
        frame[4] = (byte)((len >> 40 ) & (byte)255);
        frame[5] = (byte)((len >> 32 ) & (byte)255);
        frame[6] = (byte)((len >> 24 ) & (byte)255);
        frame[7] = (byte)((len >> 16 ) & (byte)255);
        frame[8] = (byte)((len >> 8 ) & (byte)255);
        frame[9] = (byte)(len & (byte)255);
        frameCount = 10;
    }

    int bLength = frameCount + rawData.length;

    byte[] reply = new byte[bLength];

    int bLim = 0;
    for(int i=0; i<frameCount;i++){
        reply[bLim] = frame[i];
        bLim++;
    }
    for(int i=0; i<rawData.length;i++){
        reply[bLim] = rawData[i];
        bLim++;
    }

    out.write(reply);
    out.flush();

}

3
रीड ऑपरेशन के लिए एक उपयुक्त बफर लंबाई क्या होगी?
जैकगेरिट्स

दुर्भाग्य से, यह काम नहीं करता है। मैंने अपने प्रोग्राम में केवल शून्य प्रसारण (सर्वर से क्लाइंट तक) की नकल की। सॉकेट सफलतापूर्वक कनेक्ट किया गया, संदेश सफलतापूर्वक ब्राउज़र को भेजा गया, लेकिन ब्राउज़र द्वारा प्राप्त कुछ भी नहीं।
निक

18

जावास्क्रिप्ट कार्यान्वयन:

function encodeWebSocket(bytesRaw){
    var bytesFormatted = new Array();
    bytesFormatted[0] = 129;
    if (bytesRaw.length <= 125) {
        bytesFormatted[1] = bytesRaw.length;
    } else if (bytesRaw.length >= 126 && bytesRaw.length <= 65535) {
        bytesFormatted[1] = 126;
        bytesFormatted[2] = ( bytesRaw.length >> 8 ) & 255;
        bytesFormatted[3] = ( bytesRaw.length      ) & 255;
    } else {
        bytesFormatted[1] = 127;
        bytesFormatted[2] = ( bytesRaw.length >> 56 ) & 255;
        bytesFormatted[3] = ( bytesRaw.length >> 48 ) & 255;
        bytesFormatted[4] = ( bytesRaw.length >> 40 ) & 255;
        bytesFormatted[5] = ( bytesRaw.length >> 32 ) & 255;
        bytesFormatted[6] = ( bytesRaw.length >> 24 ) & 255;
        bytesFormatted[7] = ( bytesRaw.length >> 16 ) & 255;
        bytesFormatted[8] = ( bytesRaw.length >>  8 ) & 255;
        bytesFormatted[9] = ( bytesRaw.length       ) & 255;
    }
    for (var i = 0; i < bytesRaw.length; i++){
        bytesFormatted.push(bytesRaw.charCodeAt(i));
    }
    return bytesFormatted;
}

function decodeWebSocket (data){
    var datalength = data[1] & 127;
    var indexFirstMask = 2;
    if (datalength == 126) {
        indexFirstMask = 4;
    } else if (datalength == 127) {
        indexFirstMask = 10;
    }
    var masks = data.slice(indexFirstMask,indexFirstMask + 4);
    var i = indexFirstMask + 4;
    var index = 0;
    var output = "";
    while (i < data.length) {
        output += String.fromCharCode(data[i++] ^ masks[index++ % 4]);
    }
    return output;
}

5
संभवतः यह ध्यान देने योग्य है कि जावास्क्रिप्ट वास्तव में संख्याओं से बड़ा होने का समर्थन नहीं करता है 2^31 - 1
pimvdb

13

C # कार्यान्वयन

ब्राउज़र -> सर्वर

    private String DecodeMessage(Byte[] bytes)
    {
        String incomingData = String.Empty;
        Byte secondByte = bytes[1];
        Int32 dataLength = secondByte & 127;
        Int32 indexFirstMask = 2;
        if (dataLength == 126)
            indexFirstMask = 4;
        else if (dataLength == 127)
            indexFirstMask = 10;

        IEnumerable<Byte> keys = bytes.Skip(indexFirstMask).Take(4);
        Int32 indexFirstDataByte = indexFirstMask + 4;

        Byte[] decoded = new Byte[bytes.Length - indexFirstDataByte];
        for (Int32 i = indexFirstDataByte, j = 0; i < bytes.Length; i++, j++)
        {
            decoded[j] = (Byte)(bytes[i] ^ keys.ElementAt(j % 4));
        }

        return incomingData = Encoding.UTF8.GetString(decoded, 0, decoded.Length);
    }

सर्वर -> ब्राउज़र

    private static Byte[] EncodeMessageToSend(String message)
    {
        Byte[] response;
        Byte[] bytesRaw = Encoding.UTF8.GetBytes(message);
        Byte[] frame = new Byte[10];

        Int32 indexStartRawData = -1;
        Int32 length = bytesRaw.Length;

        frame[0] = (Byte)129;
        if (length <= 125)
        {
            frame[1] = (Byte)length;
            indexStartRawData = 2;
        }
        else if (length >= 126 && length <= 65535)
        {
            frame[1] = (Byte)126;
            frame[2] = (Byte)((length >> 8) & 255);
            frame[3] = (Byte)(length & 255);
            indexStartRawData = 4;
        }
        else
        {
            frame[1] = (Byte)127;
            frame[2] = (Byte)((length >> 56) & 255);
            frame[3] = (Byte)((length >> 48) & 255);
            frame[4] = (Byte)((length >> 40) & 255);
            frame[5] = (Byte)((length >> 32) & 255);
            frame[6] = (Byte)((length >> 24) & 255);
            frame[7] = (Byte)((length >> 16) & 255);
            frame[8] = (Byte)((length >> 8) & 255);
            frame[9] = (Byte)(length & 255);

            indexStartRawData = 10;
        }

        response = new Byte[indexStartRawData + length];

        Int32 i, reponseIdx = 0;

        //Add the frame bytes to the reponse
        for (i = 0; i < indexStartRawData; i++)
        {
            response[reponseIdx] = frame[i];
            reponseIdx++;
        }

        //Add the data bytes to the response
        for (i = 0; i < length; i++)
        {
            response[reponseIdx] = bytesRaw[i];
            reponseIdx++;
        }

        return response;
    }

1
डिकोड फ़ंक्शन हमेशा मेरे लिए मेरे विशिष्ट संदेश को अपरिभाषित अपेंडिक्स के साथ लौटाता है जैसे यहां test�c=ܝX["परीक्षण" मेरा संदेश है। अन्य भाग से क्या आ रहा है?
Snickbrack

1
देर से उत्तर के लिए क्षमा करें। मैंने वेब सॉकेट को आज़माने के लिए एक छोटा सी # एप्लिकेशन (कंसोल और वेब) बनाया। आप इसे यहाँ से डाउनलोड कर सकते हैं कि यह कैसे कोडित है। लिंक: dropbox.com/s/gw8hjsov1u6f7c0/Web%20Sockets.rar?dl=0
Nitij

बड़े संदेशों पर यह मेरे लिए विफल रहा। मैंने लंबाई> 65535 कोड को इसके साथ प्रतिस्थापित किया: var l = Convert.ToUInt64 (लंबाई); var b = BitConverter.GetBytes (l); Array। उलटा (b, 0, b.Length); b.CopyTo (फ्रेम, 2); ... जो तय चीजें लगती है।
शॉन

बहुत बढ़िया। केवल एक ही चीज़: DecodeMessage पर मैं पेलोड लंबाई डेटा के आधार पर "डिकोडेड" सरणी लंबाई की गणना कर रहा हूं, जो डेटाफ्रेम पर आधारित है "बाइट्स" सरणी लंबाई सटीक नहीं हो सकती है। "बाइट्स" सरणी लंबाई स्ट्रीम पढ़ने के तरीके पर निर्भर करती है।
user1011138

@ क्या आप मुझे बड़ी संदेश समस्या को ठीक करने के लिए अपना पूर्ण उदाहरण दिखा सकते हैं? मैं उस कोड को आपके नमूने में नहीं बदल सकता।
अली यूसेफ़ी

6

अजगर में लागू pimvdb का जवाब:

def DecodedCharArrayFromByteStreamIn(stringStreamIn):
    #turn string values into opererable numeric byte values
    byteArray = [ord(character) for character in stringStreamIn]
    datalength = byteArray[1] & 127
    indexFirstMask = 2 
    if datalength == 126:
        indexFirstMask = 4
    elif datalength == 127:
        indexFirstMask = 10
    masks = [m for m in byteArray[indexFirstMask : indexFirstMask+4]]
    indexFirstDataByte = indexFirstMask + 4
    decodedChars = []
    i = indexFirstDataByte
    j = 0
    while i < len(byteArray):
        decodedChars.append( chr(byteArray[i] ^ masks[j % 4]) )
        i += 1
        j += 1
    return decodedChars

उपयोग का एक उदाहरण:

fromclient = '\x81\x8c\xff\xb8\xbd\xbd\xb7\xdd\xd1\xd1\x90\x98\xea\xd2\x8d\xd4\xd9\x9c'
# this looks like "?ŒOÇ¿¢gÓ ç\Ð=«ož" in unicode, received by server
print DecodedCharArrayFromByteStreamIn(fromclient)
# ['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!']

मैंने अपनी स्क्रिप्ट में आपके कोड का उपयोग करने की कोशिश की, लेकिन कोई सफलता नहीं मिली। क्या आप शायद मदद करने में सक्षम हो सकते हैं? stackoverflow.com/questions/43748377/…
याक

5

PHP फ्रेम एन्कोडिंग फ़ंक्शन के अलावा, यहाँ एक डिकोड फ़ंक्शन निम्न है:

function Decode($M){
    $M = array_map("ord", str_split($M));
    $L = $M[1] AND 127;

    if ($L == 126)
        $iFM = 4;
    else if ($L == 127)
        $iFM = 10;
    else
        $iFM = 2;

    $Masks = array_slice($M, $iFM, 4);

    $Out = "";
    for ($i = $iFM + 4, $j = 0; $i < count($M); $i++, $j++ ) {
        $Out .= chr($M[$i] ^ $Masks[$j % 4]);
    }
    return $Out;
}

मैंने इसे और अन्य कार्यों को यहां एक आसान-से उपयोग किए जाने वाले WebSocket PHP वर्ग में लागू किया है


4

PHP कार्यान्वयन:

function encode($message)
{
    $length = strlen($message);

    $bytesHeader = [];
    $bytesHeader[0] = 129; // 0x1 text frame (FIN + opcode)

    if ($length <= 125) {
            $bytesHeader[1] = $length;
    } else if ($length >= 126 && $length <= 65535) {
            $bytesHeader[1] = 126;
            $bytesHeader[2] = ( $length >> 8 ) & 255;
            $bytesHeader[3] = ( $length      ) & 255;
    } else {
            $bytesHeader[1] = 127;
            $bytesHeader[2] = ( $length >> 56 ) & 255;
            $bytesHeader[3] = ( $length >> 48 ) & 255;
            $bytesHeader[4] = ( $length >> 40 ) & 255;
            $bytesHeader[5] = ( $length >> 32 ) & 255;
            $bytesHeader[6] = ( $length >> 24 ) & 255;
            $bytesHeader[7] = ( $length >> 16 ) & 255;
            $bytesHeader[8] = ( $length >>  8 ) & 255;
            $bytesHeader[9] = ( $length       ) & 255;
    }

    $str = implode(array_map("chr", $bytesHeader)) . $message;

    return $str;
}

4

इस उत्तर के लिए धन्यवाद, अगर कोई दिलचस्पी रखता है, तो मैं फ़ंक्शन को शामिल करने के लिए पाइथन संस्करण को hfern (ऊपर) पर जोड़ना चाहूंगा

def DecodedWebsockRecieve(stringStreamIn):
    byteArray =  stringStreamIn 
    datalength = byteArray[1] & 127
    indexFirstMask = 2 
    if datalength == 126:
        indexFirstMask = 4
    elif datalength == 127:
        indexFirstMask = 10
    masks = [m for m in byteArray[indexFirstMask : indexFirstMask+4]]
    indexFirstDataByte = indexFirstMask + 4
    decodedChars = []
    i = indexFirstDataByte
    j = 0
    while i < len(byteArray):
        decodedChars.append( chr(byteArray[i] ^ masks[j % 4]) )
        i += 1
        j += 1
    return ''.join(decodedChars)

def EncodeWebSockSend(socket,data):
    bytesFormatted = []
    bytesFormatted.append(129)

    bytesRaw = data.encode()
    bytesLength = len(bytesRaw)
    if bytesLength <= 125 :
        bytesFormatted.append(bytesLength)
    elif bytesLength >= 126 and bytesLength <= 65535 :
        bytesFormatted.append(126)
        bytesFormatted.append( ( bytesLength >> 8 ) & 255 )
        bytesFormatted.append( bytesLength & 255 )
    else :
        bytesFormatted.append( 127 )
        bytesFormatted.append( ( bytesLength >> 56 ) & 255 )
        bytesFormatted.append( ( bytesLength >> 48 ) & 255 )
        bytesFormatted.append( ( bytesLength >> 40 ) & 255 )
        bytesFormatted.append( ( bytesLength >> 32 ) & 255 )
        bytesFormatted.append( ( bytesLength >> 24 ) & 255 )
        bytesFormatted.append( ( bytesLength >> 16 ) & 255 )
        bytesFormatted.append( ( bytesLength >>  8 ) & 255 )
        bytesFormatted.append( bytesLength & 255 )

    bytesFormatted = bytes(bytesFormatted)
    bytesFormatted = bytesFormatted + bytesRaw
    socket.send(bytesFormatted) 

पढ़ने के लिए उपयोग:

bufSize = 1024     
read = DecodedWebsockRecieve(socket.recv(bufSize))

लेखन के लिए उपयोग:

EncodeWebSockSend(sock,"hellooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo")

2

गो में कार्यान्वयन

एनकोड भाग (सर्वर -> ब्राउज़र)

func encode (message string) (result []byte) {
  rawBytes := []byte(message)
  var idxData int

  length := byte(len(rawBytes))
  if len(rawBytes) <= 125 { //one byte to store data length
    result = make([]byte, len(rawBytes) + 2)
    result[1] = length
    idxData = 2
  } else if len(rawBytes) >= 126 && len(rawBytes) <= 65535 { //two bytes to store data length
    result = make([]byte, len(rawBytes) + 4)
    result[1] = 126 //extra storage needed
    result[2] = ( length >> 8 ) & 255
    result[3] = ( length      ) & 255
    idxData = 4
  } else {
    result = make([]byte, len(rawBytes) + 10)
    result[1] = 127
    result[2] = ( length >> 56 ) & 255
    result[3] = ( length >> 48 ) & 255
    result[4] = ( length >> 40 ) & 255
    result[5] = ( length >> 32 ) & 255
    result[6] = ( length >> 24 ) & 255
    result[7] = ( length >> 16 ) & 255
    result[8] = ( length >>  8 ) & 255
    result[9] = ( length       ) & 255
    idxData = 10
  }

  result[0] = 129 //only text is supported

  // put raw data at the correct index
  for i, b := range rawBytes {
    result[idxData + i] = b
  }
  return
}

डिकोड भाग (ब्राउज़र -> सर्वर)

func decode (rawBytes []byte) string {
  var idxMask int
  if rawBytes[1] == 126 {
    idxMask = 4
  } else if rawBytes[1] == 127 {
    idxMask = 10
  } else {
    idxMask = 2
  }

  masks := rawBytes[idxMask:idxMask + 4]
  data := rawBytes[idxMask + 4:len(rawBytes)]
  decoded := make([]byte, len(rawBytes) - idxMask + 4)

  for i, b := range data {
    decoded[i] = b ^ masks[i % 4]
  }
  return string(decoded)
}

2

क्लोजर, डीकोड फ़ंक्शन मानता है कि फ्रेम को मानचित्र के रूप में भेजा जाता है {:data byte-array-buffer :size int-size-of-buffer}, क्योंकि वास्तविक आकार आपके इनपुटस्ट्रीम के चंक आकार के आधार पर बाइट-सरणी के समान आकार नहीं हो सकता है।

कोड यहां पोस्ट किया गया: https://gist.github.com/viperscape/8918565

(defn ws-decode [frame]
  "decodes websocket frame"
  (let [data (:data frame)
        dlen (bit-and (second data) 127)
        mstart (if (== dlen 127) 10 (if (== dlen 126) 4 2))
        mask (drop 2 (take (+ mstart 4) data))
        msg (make-array Byte/TYPE (- (:size frame) (+ mstart 4)))]
   (loop [i (+ mstart 4), j 0]
      (aset-byte msg j (byte (bit-xor (nth data i) (nth mask (mod j 4)))))
      (if (< i (dec(:size frame))) (recur (inc i) (inc j))))
    msg))

(defn ws-encode [data]
  "takes in bytes, return websocket frame"
  (let [len (count data)
        blen (if (> len 65535) 10 (if (> len 125) 4 2))
        buf (make-array Byte/TYPE (+ len blen))
        _ (aset-byte buf 0 -127) ;;(bit-or (unchecked-byte 0x80) 
                                           (unchecked-byte 0x1)
        _ (if (= 2 blen) 
            (aset-byte buf 1 len) ;;mask 0, len
            (do
              (dorun(map #(aset-byte buf %1 
                      (unchecked-byte (bit-and (bit-shift-right len (*(- %2 2) 8))
                                               255)))
                      (range 2 blen) (into ()(range 2 blen))))
              (aset-byte buf 1 (if (> blen 4) 127 126))))
        _ (System/arraycopy data 0 buf blen len)]
    buf))

0

सी ++ कार्यान्वयन (मेरे द्वारा नहीं) यहां । ध्यान दें कि जब आपकी बाइट्स 65535 से अधिक होती हैं, तो आपको यहां दिखाए गए अनुसार लंबे मूल्य के साथ शिफ्ट करने की आवश्यकता होती है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.