تفاوت وب‌ سوکت و Socket.io

وب‌ سوکت و Socket.ioبرای پیاده سازی ارتباطات ریل تایم در وب اپلیکیشن های مدرن، متداول ترین گزینه ها وب‌ سوکت و سرویس Socket.io هستند. در این نوشته تفاوت های این ۲ مورد رو بررسی می‌کنیم.هنگام ساخت یک برنامه ریل تایم ، لحظه ای وجود داره که باید انتخاب کنید که چگونه تبادل داده ها در زمان واقعی بین کلاینت و سرور را پیاده سازی کنید. وب سوکت و Socket.io احتمالاً دو مورد از محبوب ترین راه حل ها برای پیاده سازی ارتباطات ریل تایم در وب مدرن هستند. اما کدام یک را انتخاب کنیم؟ تفاوت این دو فناوری چیست؟ با هم بررسی می‌کنیم.وب سوکت هنگام صحبت در مورد وب سوکت ، ما به یک پروتکل ارتباطی وب اشاره می کنیم که یک کانال ارتباطی دو طرفه را از طریق یک اتصال TCP فراهم می کند. به عبارت دیگر ، امکان تعامل بین سرویس گیرنده (کلاینت) و سرور را با حداقل هزینه و بار ممکن می‌سازد و به ما امکان می دهد برنامه هایی بسازیم که از مزایای ارتباطات لحظه ای استفاده می کنند.توسعه دادن یک اپلیکیشن برای چت را در نظر بگیرید: باید در اسرع وقت داده ها را دریافت و ارسال کنید، پس انجام این کار با وب سوکت سناریوی مناسب است! می توانید یک اتصال TCP را باز کرده و داده ها را به اشتراک بگذارید و اتصال را تا زمانی که به آن نیاز دارید باز بگذارید. وب سوکت اولین بار در سال ۲۰۱۰ در گوگل کروم ۴ ظاهر شد و اولین RFC مربوط (RFC ۶۴۵۵) یک سال بعد ، در سال ۲۰۱۱ منتشر شد. غیر از مثال بالا گزینه های زیر هم موارد خوبی برای استفاده از وب سوکت هستند: بازی های چند نفره ویرایش های مشارکتی برنامه های مبتنی بر مکانفیدهای اجتماعی و غیره و اما Socket.ioکتابخانه Socket.io یک کتابخانه جاوا اسکریپتی است که بر مبنای وب سوکت و چند تکنولوژی دیگر توسعه داده شده است. Socket.io در مواقعی که وب ‌سوکت مهیا باشد از آن استفاده میکند، و در غیر این صورت از تکنولوژی هایی مثل Flash Socket, AJAX Long Polling, AJAX Multipart Stream بهره می‌برد.تفاوت هامزایای اصلی Socket.io نسبت به وب سوکت عبارتند از:بر خلاف وب سوکت، socket.io به شما امکان می‌دهد تا برای همه کلاینت های متصل پیام ارسال کنید. به عنوان مثال ، اگر در حال نوشتن برنامه چت هستید و می خواهید به همه کاربران متصل اطلاع دهید که کاربر جدیدی به چت پیوسته است ، می توانید به راحتی آن پیام را برای همه کاربران برادکست (Broadcast) کنید; در حالی که با استفاده از وب سوکت ساده ، به یک لیست از کلاینت های متصل نیاز دارید و سپس پیام را مستقیماً یکی یکی ارسال می کنید.لود بالانسر ها (Load Balancer) و پراکسی ها پیاده سازی و مقیاس پذیری وب سوکت را سخت میکنند. در حالی که Socket.io به صورت پیش‌فرض این موارد را برطرف می‌کند.همان طور که گفتیم Socket.io در صورت نیاز می تواند از تکنولوژی های دیگر هم استفاده کند.اگر (به هر دلیلی) اتصال وب سوکت قطع شود ، به طور خودکار دوباره وصل نمی شود ... اما حدس بزنید چی؟ Socket.io خودش این کار رو برای ما انجام میده.استفاده کردن از Socket.io به مراتب ساده تره.می‌بینید که به نظر میرسه Socket.io بهترین گزینه برای ارتباطات ریل تایم باشه... اما برخی مواقع دلایل خوبی هم وجود دارند که استفاده از وب سوکت ساده رو توجیح می‌کنند..اول از همه ، هر مرورگر مدرن این روزها از وب سوکت پشتیبانی می کند. Socket.io برای فال‌بک به تکنولوژی های دیگه از منابع بیشتری استفاده میکند. که بیشتر اوقات هم، به این سطح از پشتیبانی نیازی نداریم; همچنین Socket.io منابع بیشتری از ترافیک شبکه را هم استفاده می‌کند. در حالی که با وب سوکت ساده، مرورگر احتمالا ۲ درخواست ساده را اجرا می‌کند:درخواست Get برای صفحه وبآپگرید اتصال برای وب سوکتو به همین سادگی شما آماده شروع ارتباط ریل تایم با سرور خود هستید! اما با Socket.io چطور؟درخواست Get برای صفحه وببارگذاری کتابخانه کلاینت Socket.io - با حجم ۲۲۰ کیلوبایتسه درخواست Ajax Long Pollingآپگرید اتصال برای وب سوکتیک پکیج هم در npm به نام websocket-vs-socket.io وجود دارد که برای مقایسه ترافیک شبکه این دو فناوری ساخته شده است. البته در یک مرورگر هم میتونید تفاوت زیاد در منابع شبکه رو بررسی کنید.ترافیک شبکه وب سوکت:ترافیک شبکه وب سوکتترافیک شبکه Socket.io:ترافیک شبکه Socket.ioنوشتن کدهای ریل تایم (بلا درنگ)مقایسه ای که تا اینجا انجام دادیم، در واقع مقایسه ای روی کاغذ بوده. اما این تکنولوژی ها در حین نوشتن برنامه های ریل تایم چه تفاوتی ایجاد می‌کنند؟با استفاده از وب سوکت ساده ، در برنامه Node.js ای زیر، یک وب سوکت سرور روی پورت ۳۰۰۰ ایجاد می‌کنیم.. هر بار که کلاینتی متصل شود، ما یک شناسه منحصر به فرد برای Session آن کلاینت در نظر می‌گیریم. و زمانی که کلاینت پیامی ارسال می‌کند، با چنین فرمتی ( [<client-id>]: <message> ) پاسخ می‌دهیم. پس کلاینت می‌داند که پیام با موفقیت ارسال شده است.Plain Websockets Serverبسیار خب. اما اگر بخواهیم این پیام را برای تمام کلاینت های متصل ارسال کنیم، چی؟ وب سوکت به طور پیش فرض چنین ویژگی رو پشتیبانی نمی‌کنه اما پیاده سازی اش کار پیچیده ای هم نیست:Iteration on Websockets Serverهمان طور که مشاهده می کنید ، سرور وب سوکت هر کلاینت متصل را ردیابی می کند ، بنابراین می توانیم روی آنها حلقه بزنیم و پیام مورد نظر را برای همه ارسال کنیم. به این ترتیب ما ساده ترین سرور چت ممکن را پیاده سازی کردیم. می توانید کد بالا را با یک کلاینت وب سوکتی در دسکتاپ و یا از طریق یک اکستنشن کروم تست کنید.بسیار خوب. حالا قصد داریم کد بالا رو با کتابخانه Socket.io پیاده سازی کنیم.Socket.io implementation of the same codeبا استفاده از متد broadcast که به شکل نیتیو پیاده سازی شده، می‌بینید که کد ها تقریبا نصف وب سوکت ساده هستند و می تونیم پیام ها رو برای تمام کاربران متصل ارسال کنیم. فقط یک مشکل داریم.. تست کردن این کد روی یک وب سوکت کلاینت معمولی ، امکان پذیر نیست. به این دلیل که (همانطور که قبلاً گفته شد) ، Socket.io از وب سوکت ساده استفاده نمی‌کند ، در عوض چندین فناوری را برای پشتیبانی از بیشترین تعداد کلاینت ها ترکیب می کند. برای تست این اپلیکیشن به کتابخانه کلاینت Socket.io نیاز داریم; که در مثال زیر از طریق CDN آن را فراهم کرده ایم.همانطور که مشاهده می‌کنید ، ممکنه این دو مثال چندان متفاوت به نظر نرسند ... اما Socket.io همواره به کتابخانه کلاینت خود نیاز دارد ، بنابراین نمی توانید از آن برای مقاصدی غیر از توسعه وب استفاده کنید. این در حالی است که وب سوکت ممکن است برای حل مجموعه بزرگی از مشکلات مانند ارتباطات P2P ، انتقال داده سرور به سرور و غیره به صورت بلا درنگ استفاده شود.مواردی که باید به یاد داشتهمان طور که با هم بررسی کردیم ، مشکلاتی وجود داره که Socket.io سعی در حل آنها دارد.مقیاس پذیری فرض کنید که برنامه چت شما موفقیت زیادی کسب کرده است و شما برای هندل کردن همه درخواست ها باید یک سرور دیگر و یک لود بالانسر (Load Balancer) اضافه کنید. حال، اگر در حال اتصال به "سرور ۱" باشید، اما لود بالانسر شما را به "سرور ۲" سوئیچ کند، با خطای زیر مواجه خواهید شد: Error during WebSocket handshake: Unexpected response code: 400خوب Socket.io با استفاده از یک کوکی (یا مسیریابی اتصال بر اساس آدرس اصلی آنها) این مشکل را حل می کند ، اما وب سوکت مکانیزم جایگزینی را به شکل پیش فرض ارائه نمی دهد.عملکرد (پرفرمنس)همانطور که قبلاً گفتیم ، Socket.io چندین لایه انتزاع را بر روی لایه انتقال وب سوکت فراهم می کند. همچنین استفاده از JSON را برای ارسال داده های باینری از کلاینت به سرور (و بالعکس) اعمال می کند. پس اگر نیاز به پرفرمنس بالا داشته باشید باید کتابخانه را کاستومایز کنید تا از این رفتار خاص جلوگیری کنید; در صورتی که با وب سوکت چنین مشکلی نخواهید داشت.انتخابمی‌بینید که انتخاب بین این ۲ گزینه کمی مشکل است. خوب Socket.io مسلما کمی کار رو راحت تر میکنه، و لازم نیست نگران مواردی مثل لود بالانسینگ، قطع اتصال و برادکستینگ باشیم. سوالی که پیش میاد اینه که:‌ آیا واقعا به تمام این فیچرها نیاز داریم؟ چون فقط کتابخانه کلاینت Socket.io به تنهایی سنگین تر از React, Redux و React-Redux است.نکته دیگری که باید به خاطر داشته باشید این است که Socket.io سمت سرور پیاده سازی شده و یک کتابخانه سفارشی است که در بیشتر اوقات ، به دلیل انتزاعات اعمال شده توسط خود Socket.io ، از منطق وب سوکت ساده پیروی نمی کند. پس اگر قرار باشه میکرو سرویس های Node.js تون رو ریفکتور کنید و به سمت Java, Go و یا هر زبان دیگه مهاجرت کنید، باید بیشتر منطق Socket.io را بازنویسی کنید تا نتایج مشابهی را با وب‌سوکت ساده بدست آورید. برادکست کردن پیام ها رو به کلاینت های آنلاین در نظر بگیرید.. درسته که با Socket.io این کار به سادگی استفاده از یک متد هست (اما در وب سوکت ساده باید دستی پیاده سازی شود) .. اما در حین استفاده از وب سوکت ساده، ریفکتور، توسعه و پیاده سازی ویژگی های جدید به مراتب در پروژه های کاستومایز شده، ساده تر است.