หมายเหตุ: นี่คือคำอธิบายและรหัสเทียมเกี่ยวกับวิธีการใช้งานเซิร์ฟเวอร์ที่ไม่สำคัญซึ่งสามารถจัดการกับข้อความ WebSocket ขาเข้าและขาออกตามรูปแบบการจัดเฟรมขั้นสุดท้าย ยังไม่รวมขั้นตอนการจับมือ นอกจากนี้คำตอบนี้จัดทำขึ้นเพื่อวัตถุประสงค์ทางการศึกษา ไม่ใช่การใช้งานแบบเต็มรูปแบบ
ข้อมูลจำเพาะ (RFC 6455)
การส่งข้อความ
(กล่าวอีกนัยหนึ่งเซิร์ฟเวอร์→เบราว์เซอร์)
เฟรมที่คุณส่งจะต้องได้รับการจัดรูปแบบตามรูปแบบเฟรม WebSocket สำหรับการส่งข้อความรูปแบบนี้มีดังนี้:
- หนึ่งไบต์ซึ่งมีประเภทของข้อมูล (และข้อมูลเพิ่มเติมบางอย่างที่อยู่นอกขอบเขตสำหรับเซิร์ฟเวอร์เล็กน้อย)
- หนึ่งไบต์ซึ่งมีความยาว
- สองหรือแปดไบต์หากความยาวไม่พอดีกับไบต์ที่สอง (ไบต์ที่สองจะเป็นรหัสที่บอกว่าใช้ความยาวกี่ไบต์)
- ข้อมูลจริง (ดิบ)
ไบต์แรกจะเป็น1000 0001
(หรือ129
) สำหรับกรอบข้อความ
ไบต์ที่สองมีบิตแรกที่ตั้งค่าเป็น0
เนื่องจากเราไม่ได้เข้ารหัสข้อมูล (การเข้ารหัสจากเซิร์ฟเวอร์ไปยังไคลเอนต์ไม่บังคับ)
จำเป็นต้องกำหนดความยาวของข้อมูลดิบเพื่อที่จะส่งไบต์ความยาวได้อย่างถูกต้อง:
- ถ้า
0 <= length <= 125
คุณไม่ต้องการไบต์เพิ่มเติม
- ถ้า
126 <= length <= 65535
คุณต้องการสองไบต์เพิ่มเติมและไบต์ที่สองคือ126
- ถ้า
length >= 65536
คุณต้องการแปดไบต์เพิ่มเติมและไบต์ที่สองคือ127
ความยาวจะต้องถูกแบ่งออกเป็นไบต์ที่แยกจากกันซึ่งหมายความว่าคุณจะต้องเลื่อนบิตไปทางขวา (ด้วยจำนวนแปดบิต) จากนั้นคงไว้เฉพาะแปดบิตสุดท้ายโดยทำAND 1111 1111
(ซึ่งก็คือ255
)
หลังจากความยาวไบต์มาข้อมูลดิบ
สิ่งนี้นำไปสู่ pseudocode ต่อไปนี้:
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
เป็นดัชนี (offset) ของการนับไบต์จากไบต์แรกของข้อมูลจริง0
ซึ่งมีดัชนี masks
คืออาร์เรย์ที่มีมาสก์สี่ไบต์
สิ่งนี้นำไปสู่ pseudocode ต่อไปนี้สำหรับการถอดรหัส:
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
) หรือ?