محسن پورعینی
محسن پورعینی
خواندن ۶ دقیقه·۳ ماه پیش

در اعماق وب سوکت چه میگذرد؟

WebSocket پروتکل برقراری ارتباط دوطرفه و Real-Time
WebSocket پروتکل برقراری ارتباط دوطرفه و Real-Time

معمولا هرجا صحبت از Real-Time بودن و چت یا گیمینگ و ... کلا هر نوع از ارتباطی که مداوم و در لحظه باشه معمولا رد پای WebSocket دیده میشه، حالا یا خودش یا پسر خوندش (کتاب خونه Socket.IO)

همیشه بهمون میگن پروتکل WebSocket یک پروتکل دوطرفه است و اصطلاحاتی مثل Full Duplex و Bidirectional رو همراه وب سکوت دیدیم.
احتمالا شما که دارید این مقاله رو میخونید قبلا حداقل یک بار از وب سکوت استفاده کردید یا حداقل تو پروژه دیدید.

میخواییم بدونیم اصلا یک Connection وب سکوت چطور برقرار میشه، چطور پایدار میمونه، چطور بسته های حجیم رو جا به جا میکنه بدون اینکه کسی رو اذیت کنه و در آخر درمورد ارور هندلینگ ها و مزایا و معایب و یکم هم درمورد جایگزین هاش صحبت میکنیم.


1. چگونه به تفاهم رسیدیم؟

در ب بسم الله یک کانکشن وب سکوت از یک ریکوئست HTTP شروع میشه. در واقع یک ریکوئست HTTP با هدر Upgrade: websocket از طرف کلاینت به سرور فرستاده میشه. درصورتی که سرور از وب سوکت پشتیبانی کنه به اون ریکوئست جواب بله رو میده ( حالا با مثال میبینیم مراحل رو)

اول یک نگاه بندازیم به این ریکوئست HTTP که قدم اول Handshake وب سکوت ما و سرور هست:

GET /chat HTTP/1.1 Host: api.mopoy.ir Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: 1Tzi+sYL+4QtM0lQUzu5Zw== Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13 Origin: http://mopoy.ir


  • هدر Connection به سرور میگه که کلاینت میخواد درمورد نوع ارتباطی تصمیمات جدیدی بگیره(میخواد با سرور مذاکره کنه)، که اینجا میگه میخواد آپدیت کنه نوع ارتباط رو.
  • این ریکوئست برای سوییچ کردن پروتکل به وب سکوت از طرح کلاینت ارسال میشه، مشخصا اگه سرور از وب سکوت پشتیبانی کنه باید به این ریکوئست جواب بده، تا اینجا اوکیه. سه تا هدر جدید هم به چشم میخوره تو این ریکوئست:
    Sec-WebSocket-Key:
    کلاینت برای اینکه بفهمه سرور دقیقا حرفشو میفهمه نیاز به یک تضمین داره! و اون تضمین یک nounce
    16 بیتی رندوم هست که سمت کلاینت ساخته میشه و base64 encode میشه و با این هدر میفرسته سمت سرور. سرور هم باید یک GUID تولید کنه و بچسبونه به این کلید و با SHA-1 هش کنه و بفرسته سمت کلاینت

    Sec-WebSocket-Protocol:
    کلاینت باید ساب پروتکل هایی که میتونه باهاش کار کنه رو به سرور بفرسته و سرور یکی از اینا رو انتخاب میکنه و در Response بهش برمیگردونه. بعدا بیشتر درموردش صحبت میکنم...

    آخری هم که ورژن هست که فقط همون 13 مورد قبوله (تاجایی که من میدونم).

    خب، حالا این ریکوئست ارسال شد سرور باید چی برگردونه؟ یه نمونه ببینیم:
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: Jsbx+rL41g/L+BDIlMTM6zH4QbKs1w== Sec-WebSocket-Protocol: chat


مشخصا اگه جواب بله بود با یک Http Response 101 که به معنی تغییر پروتکل هست طرفیم.

Sec-WebSocket-Accept جواب هش شده و base64 همون Sec-WebSocket-Key هست که کلاینت فرستاده بود.
Sec-WebSocket-Protocol هم ساب پروتوکل انتخابی سرور هست
انتخاب ساب پروتکل توسط سرور به این شکل هست که کلاینت لیست ساب پروتکل های که میتونه و میخواد استفاده کنه رو به ترتیب الویت (اولی بالاترین الویت) برای سرور میفرسته و سرور نگاه میکنه اولین پروتکلی که براش قابل استفاده هست رو انتخاب میکنه و برای کلاینت بر میگردونه.
درمورد ساب پروتکل ها بعدا بیشتر صحبت میکنیم.


پس تا اینجا سرور و کلاینت به تفاهم رسیدن و کانکشن وب سکوت بینشون برقراره.

پ.ن: اصولا وقتی دارید از یک کتابخونه برای وب سکوت استفاده میکنید یا اگه تو وب هستید، آبجکت WebSocket مرورگر رو صدا میزنید، همه این کار ها ( Handshake و...) اتوماتیک انجام میشه و نیاز نیز باهاش درگیر بشید.

2. ساختار پیام:

WS Frame Struct (RFC 6455)
WS Frame Struct (RFC 6455)

طبق این نمودار که RFC وب سکوت ارائه داده، ساختار یک فریم پیام وب سکوت به این صورت هست. بیایید بخش های مختلف این نمودار و اجزای یک فریم وب سکوت رو با مثال بررسی کنیم.

بعد از اینکه Handshake میان کلاینت و سرور اتفاق افتاد تبادل دیتا بین کلاینت و سرور شروع میشه
مثلا این یک نمونه دیتایی هست که میتونه از کلاینت به سرور ارسال بشه:

0x81 0x05 0x48 0x65 0x6c 0x6c 0x6f یا بصورت 0x81\0x05\Hello

این یک نمونه ساده Frame وب سوکت هست حاوی پیام Hello (فریم Unmasked)


بیایید از اولین بخش این پیام شروع کنیم، اولین عدد Hex این پیام (که اینجا 0x81 هستش) به ما چند تا چیز رو نشون میده، FIN, opcode, frame type و اکستنشن ها (درصورت استفاده)
بیایید دونه دونه این هارو بررسی کنیم ببنیم چی هستن.

0x81

اول از همه این عدد رو اگه به باینری تبدیل کنیم میرسیم به ->

Byte2 : 1000 0001

از سمت چپ اولین عدد "1" میشه همون FIN، این وقتی برای پیام های Fragment یا همون تکه تکه شده کاربرد داره که تو بخش بعدی مفصل بررسی میکنیمش. درحالت کلی این بیت FIN اگه صفر باشه یعنی پیام تکه تکه شده و هنوز ادامه داره ولی اگه یک باشه یعنی آخرین بخش پیامه (یا اینکه پیام تکه تکه نشده و کلا همین یدونه هست)


سه تا بیت بعدی از همین بایت بیت های رزرو هستن برای اکستنشن ها، هرکدوم از اینا اگر یک باشن اکستنشن مربوطه (اگر سرور پشتبیانی کنه) استفاده میشه. درمورد اکستنشن ها تو بخش خودش صحبت میکنیم اصلا چی هستن و برای چه کاری میان فعلا تا همینجا کافیه.

چهار بیت بعدی ،که میشه بایت دوم، opcode هست، اونایی که قبلا شبکه کار کردن و با پروتکل ها آشنایی دارن میدون opcode چیه، اینجا یه مختصری بهش اشاره میکنیم. درحالت کلی آپ کد نوع پیام یا نوع کاری که پیام قراره انجام بده رو معمولا مشخص میکنه اینجا تو وب سکوت از 0 تا 15 (0 تا F) که میشه 0000 تا 1111 داخل بایت، آپ کد داریم که دونه دونه بررسیشون میکنیم


0: آپ کد صفر یعنی اینکه این فریم ادامه فریم های قبلیه (پیام فرگمنت شده) و از قبلی ها تبعیت میکنه
1: آپ کد یک میگه محتوای پیام یک text UTF-8 معمولیه
2: آپ کد دو میگه محتوای پیام یه باینریه ( هرچیزی عملا میتونه باشه، یه جاهایی کاربرد جالب داره بعدا اگه شد نگاه میکنیم بهش)
3-7: آپ کد های سه تا هفت هم رزرو هستن برای دیتا فریم های سفارشی
8: آپ کد 8 کانکشن رو terminate میکنه (میبنده)
9-10: آپ کد 9 و 10 برای پینگ هست، وقتی یک کانکشن وب سکوت درجریان هرزگاهی کلاینت یه مسیج پینگ برای سرور میفرسته تا مطمعن بشه هنوز کانکشن برقراره، در جواب باید مسیج با آپ کد 10 از سرور بگیره
11-15: آپ کد های یازده تا پانزده هم رزرو هستن برای کنترل فریم های سفارشی

بعد از این میرسیم به بخش دوم پیام یعنی 0x05
اگه اینو به باینری تبدیل کنیم میشه 0101


3. پیام تکه تکه شده:



3. من هنوز یک کانکشن پایدار هستم! :

یک کانکشن وب سوکت ذاتا یک کانکشن مداوم و پایدار هست، یعنی تا زمانی که لازم داریم میتونیم ارتباط رو باز نگه داریم و مکاتبه کنیم. از نظر تئوری برای همیشه میتونه این ارتباط باز باشه ولی میدونیم که در عملا همچین چیزی نیست، مشکلات شبکه،packet loss و issue های سمت سرور و کلاینت و صد ها عامل دیگه ممکنه این کانکشن رو به خطر بندازه و هر آن قطع بشه.
چند تا مسئله رو بیایید بررسی کنیم:
اول اینکه چی باعث میشه یک کانکشن وب سکوت پایدار باشه. و چه عواملی میتونه باعث از دست دادن این ارتباط بشه. کلاینت و سرور چطور میفهمن که هنوز کانکشن پایداره و اون سمت مشکلی نیست؟

و در نهایت اگه مشکلی پیش اومد یا packet loss اتفاق افتاد چی پیش میاد؟


قبل از اینکه بخواییم به اینا بپردازیم بیایید ببینیم اصلا وب سکوت چطور با کمترین میزان Overhead برای سرور و شبکه، دیتا های حجیم و Bulk رو Transmitمیکنه.



درحال نوشتن...

وبوب سوکتسمت سرورسمت کلاینتوب سکوت
اینجا درمورد هرچیزی که احساس میکنم مفید هست صحبت میکنم.
شاید از این پست‌ها خوشتان بیاید