2011-08-12 14 views
8

चूंकि क्रोम v14 में अपडेट किया गया था, इसलिए वे version three of the draft से version eight of the draft पर गए थे।WebSockets hybi 08+ में डेटा फ्रेम कैसे बनाएं (डी)?

मेरे पास वेबसॉकेट पर एक आंतरिक चैट एप्लिकेशन चल रहा है, और हालांकि मुझे नया हैंडशेक काम कर रहा है, डेटा फ्रेमिंग स्पष्ट रूप से बदल गई है। मेरा वेबसाकेट सर्वर Nugget पर आधारित है।

क्या किसी के पास वेबसाफ्ट ड्राफ्ट के संस्करण आठ के साथ काम कर रहा है और तार पर डेटा को फ्रेम करने के तरीके पर एक उदाहरण है?

उत्तर

16

(यह भी देखें: How can I send and receive WebSocket messages on the server side?)


यह काफी आसान है, लेकिन यह प्रारूप को समझने के लिए महत्वपूर्ण है।

पहले बाइट, 1000 0001, जहां 1 का अर्थ है "अंतिम फ्रेम" लगभग हमेशा तीन 0 किसी भी अर्थ के बिना बिट्स आरक्षित हैं और अब तक 0001 मतलब है कि यह एक पाठ फ्रेम (क्रोम ws.send() विधि के साथ भेजता है जो है)।

(अद्यतन:।। Chrome अब भी एक ArrayBuffer के साथ द्विआधारी फ्रेम भेज सकते हैं ताकि आप पाठ और बाइनरी डेटा के बीच अंतर आ सकता है पहला बाइट के अंतिम चार बिट्स, 0002 हो जाएगा डेटा की डिकोडिंग वास्तव में काम करता है वैसे ही।)

दूसरे बाइट में 1 (जिसका अर्थ है कि यह "मुखौटा" (एन्कोडेड) है) के बाद फ्रेम आकार का प्रतिनिधित्व करने वाले सात बिट्स हैं। यदि यह 000 0000 और 111 1101 के बीच है, तो यह आकार है। यदि यह 111 1110 है, तो निम्न 2 बाइट लंबाई हैं (क्योंकि यह सात बिट्स में फिट नहीं होगा), और यदि यह 111 1111 है, तो निम्न 8 बाइट लंबाई हैं (यदि यह दो बाइट्स में फिट नहीं होगा)।

निम्नलिखित चार बाइट्स हैं जो "मास्क" हैं जिन्हें आपको फ्रेम डेटा को डीकोड करने की आवश्यकता है। यह xor एन्कोडिंग का उपयोग करके किया जाता है जो डेटा के indexOfByteInData mod 4 द्वारा परिभाषित मास्क में से एक का उपयोग करता है। डिकोडिंग बस encodedByte xor maskByte (जहां maskByteindexOfByteInData mod 4 है) की तरह काम करता है।

अब मैं कहना होगा मैं के साथ सी # बिल्कुल अनुभव नहीं कर रहा हूँ, लेकिन यह कुछ स्यूडोकोड (कुछ जावास्क्रिप्ट लहजे मुझे डर लग रहा है):

var length_code = bytes[1] & 127, // remove the first 1 by doing '& 127' 
    masks, 
    data; 

if(length_code === 126) { 
    masks = bytes.slice(4, 8); // 'slice' returns part of the byte array 
    data = bytes.slice(8);  // and accepts 'start' (inclusively) 
} else if(length_code === 127) { // and 'end' (exclusively) as arguments 
    masks = bytes.slice(10, 14); // Passing no 'end' makes 'end' the length 
    data = bytes.slice(14);  // of the array 
} else { 
    masks = bytes.slice(2, 6); 
    data = bytes.slice(6); 
} 

// 'map' replaces each element in the array as per a specified function 
// (each element will be replaced with what is returned by the function) 
// The passed function accepts the value and index of the element as its 
// arguments 
var decoded = data.map(function(byte, index) { // index === 0 for the first byte 
    return byte^masks[ index % 4 ];   // of 'data', not of 'bytes' 
    //   xor   mod 
}); 

तुम भी the specification जो सहायक हो सकता है डाउनलोड कर सकते हैं (इसमें निश्चित रूप से प्रारूप को समझने के लिए आवश्यक सब कुछ शामिल है)।

+0

स्वीट ... मैं इसे सोमवार को काम पर आज़माउंगा। अगर यह काम करता है तो मैं आपको स्वीकार्य उत्तर दूंगा ... :) – gislikonrad

+0

अंत में मेरे वेबसाइकिल सर्वर के लिए इस समाधान को देखने के लिए मिल गया। एक आकर्षण की तरह काम किया ... धन्यवाद, आदमी ... – gislikonrad

+0

@ गिसली Konráð: महान यह आपके लिए काम किया; WebSockets वास्तव में डीबगिंग-अनुकूल नहीं हैं। – pimvdb

2

अधिक सटीक होने के लिए, क्रोम प्रोटोकॉल के HyBi-10 संस्करण में प्रोटोकॉल के Hixie-76 संस्करण से चला गया है। HyBi-08 HyBi-10 के माध्यम से सभी रिपोर्ट 8 संस्करण के रूप में है क्योंकि यह वास्तव में केवल विनिर्देश पाठ था जो बदल गया था और तार प्रारूप नहीं।

फ्रेमिंग प्रत्येक फ्रेम के लिए 2-7 बाइट हेडर का उपयोग करने के लिए '\ x00 ... \ xff' का उपयोग करने से बदल गई है जिसमें अन्य चीजों के साथ पेलोड की लंबाई शामिल है। विनिर्देश के section 4.2 में फ्रेम प्रारूप का एक आरेख है। यह भी ध्यान रखें कि क्लाइंट (ब्राउज़र) से सर्वर पर डेटा मास्क किया गया है (क्लाइंट-सर्वर फ्रेम हेडर के 4 बाइट्स अनमास्किंग कुंजी होते हैं)।

आप websockify देख सकते हैं जो कि noVNC का समर्थन करने के लिए बनाए गए टीसीपी सॉकेट प्रॉक्सी/पुल के लिए एक वेबसाकेट है। इसे पायथन में लागू किया गया है लेकिन आपको encode_hybi और decode_hybi दिनचर्या से विचार प्राप्त करने में सक्षम होना चाहिए।

8

यह सी # कोड मेरे लिए ठीक काम करता है। सॉकेट के माध्यम से ब्राउज़र से सी # सर्वर पर आने वाले टेक्स्ट डेटा को डीकोड करें।

public static string GetDecodedData(byte[] buffer, int length) 
    { 
     byte b = buffer[1]; 
     int dataLength = 0; 
     int totalLength = 0; 
     int keyIndex = 0; 

     if (b - 128 <= 125) 
     { 
      dataLength = b - 128; 
      keyIndex = 2; 
      totalLength = dataLength + 6; 
     } 

     if (b - 128 == 126) 
     { 
      dataLength = BitConverter.ToInt16(new byte[] { buffer[3], buffer[2] }, 0); 
      keyIndex = 4; 
      totalLength = dataLength + 8; 
     } 

     if (b - 128 == 127) 
     { 
      dataLength = (int)BitConverter.ToInt64(new byte[] { buffer[9], buffer[8], buffer[7], buffer[6], buffer[5], buffer[4], buffer[3], buffer[2] }, 0); 
      keyIndex = 10; 
      totalLength = dataLength + 14; 
     } 

     if (totalLength > length) 
      throw new Exception("The buffer length is small than the data length"); 

     byte[] key = new byte[] { buffer[keyIndex], buffer[keyIndex + 1], buffer[keyIndex + 2], buffer[keyIndex + 3] }; 

     int dataIndex = keyIndex + 4; 
     int count = 0; 
     for (int i = dataIndex; i < totalLength; i++) 
     { 
      buffer[i] = (byte)(buffer[i]^key[count % 4]); 
      count++; 
     } 

     return Encoding.ASCII.GetString(buffer, dataIndex, dataLength); 
    } 
+0

प्रश्न के अनुसार इसे उत्तर के रूप में चिह्नित किया जाना चाहिए (सी # कोड) – cdie

+0

'कुल लंबाई' क्या है और आप इसे 'keyIndex + 4' क्यों जोड़ रहे हैं? –