مشکل: اتصالات سرویس گیرنده-سرور و سرور-کلاینت با تاخیر کم
وب تا حد زیادی حول پارادایم به اصطلاح درخواست/پاسخ HTTP ساخته شده است. مشتری یک صفحه وب را بارگذاری می کند و سپس هیچ اتفاقی نمی افتد تا زمانی که کاربر روی صفحه بعدی کلیک کند. در حدود سال 2005، AJAX شروع به ایجاد پویایی بیشتر در وب کرد. با این حال، تمام ارتباطات HTTP توسط کلاینت هدایت می شد که نیاز به تعامل کاربر یا نظرسنجی دوره ای برای بارگیری داده های جدید از سرور داشت.
فناوریهایی که سرور را قادر میسازد تا دادهها را در لحظهای که میداند دادههای جدید در دسترس است ارسال کند، مدت زیادی است که وجود داشتهاند. آنها با نام هایی مانند "فشار" یا "دنباله دار" خوانده می شوند. یکی از رایجترین هکها برای ایجاد توهم اتصال آغاز شده توسط سرور، نظرسنجی طولانی نامیده میشود. با نظرسنجی طولانی، مشتری یک اتصال HTTP را به سرور باز می کند که آن را تا زمان ارسال پاسخ باز نگه می دارد. هر زمان که سرور واقعاً دادههای جدیدی داشته باشد، پاسخ را ارسال میکند (تکنیکهای دیگر شامل درخواستهای چند قسمتی Flash ، XHR و به اصطلاح فایلهای html ) هستند. نظرسنجی طولانی و تکنیک های دیگر بسیار خوب کار می کنند. شما هر روز از آنها در برنامه هایی مانند چت GMail استفاده می کنید.
با این حال، همه این راهحلها یک مشکل مشترک دارند: آنها سربار HTTP را به همراه دارند، که آنها را برای برنامههای با تأخیر کم مناسب نمیسازد. به بازی های تیراندازی اول شخص چندنفره در مرورگر یا هر بازی آنلاین دیگری با مولفه بلادرنگ فکر کنید.
معرفی WebSocket: آوردن سوکت ها به وب
مشخصات WebSocket یک API را تعریف می کند که اتصالات "سوکت" را بین یک مرورگر وب و یک سرور برقرار می کند. به عبارت ساده: یک ارتباط دائمی بین مشتری و سرور وجود دارد و هر دو طرف می توانند در هر زمان شروع به ارسال داده کنند.
شروع به کار
شما یک اتصال WebSocket را به سادگی با فراخوانی سازنده WebSocket باز می کنید:
var connection = new WebSocket('ws://html5rocks.websocket.org/echo', ['soap', 'xmpp']);
به ws:
. این طرح URL جدید برای اتصالات WebSocket است. همچنین wss:
برای اتصال ایمن WebSocket از طریق https:
برای اتصالات HTTP ایمن استفاده می شود.
پیوستن برخی از کنترلکنندههای رویداد بلافاصله به اتصال به شما این امکان را میدهد که بدانید چه زمانی اتصال باز شده، پیامهای دریافتی دریافت کردهاید یا خطایی وجود دارد.
آرگومان دوم پروتکل های فرعی اختیاری را می پذیرد. این می تواند یک رشته یا آرایه ای از رشته ها باشد. هر رشته باید یک نام زیر پروتکل را نشان دهد و سرور فقط یکی از زیر پروتکل های ارسال شده در آرایه را می پذیرد. زیر پروتکل پذیرفته شده را می توان با دسترسی به ویژگی protocol
شی WebSocket تعیین کرد.
نام های زیر پروتکل باید یکی از نام های زیر پروتکل ثبت شده در رجیستری IANA باشد. در حال حاضر تنها یک نام زیر پروتکل (صابون) تا فوریه 2012 ثبت شده است.
// When the connection is open, send some data to the server
connection.onopen = function () {
connection.send('Ping'); // Send the message 'Ping' to the server
};
// Log errors
connection.onerror = function (error) {
console.log('WebSocket Error ' + error);
};
// Log messages from the server
connection.onmessage = function (e) {
console.log('Server: ' + e.data);
};
ارتباط با سرور
به محض اتصال به سرور (هنگامی که رویداد open
فعال میشود) میتوانیم با استفاده از روش send('your message')
روی شی اتصال شروع به ارسال داده به سرور کنیم. قبلاً فقط رشته ها را پشتیبانی می کرد، اما در آخرین مشخصات اکنون می تواند پیام های باینری نیز ارسال کند. برای ارسال داده های باینری، می توانید از آبجکت Blob
یا ArrayBuffer
استفاده کنید.
// Sending String
connection.send('your message');
// Sending canvas ImageData as ArrayBuffer
var img = canvas_context.getImageData(0, 0, 400, 320);
var binary = new Uint8Array(img.data.length);
for (var i = 0; i < img.data.length; i++) {
binary[i] = img.data[i];
}
connection.send(binary.buffer);
// Sending file as Blob
var file = document.querySelector('input[type="file"]').files[0];
connection.send(file);
به همین ترتیب سرور ممکن است در هر زمان برای ما پیام ارسال کند. هر زمان که این اتفاق بیفتد، یک onmessage
پاسخ به تماس فعال می شود. پاسخ تماس یک شی رویداد را دریافت می کند و پیام واقعی از طریق ویژگی data
قابل دسترسی است.
WebSocket همچنین می تواند پیام های باینری را در آخرین مشخصات دریافت کند. فریم های باینری را می توان در قالب Blob
یا ArrayBuffer
دریافت کرد. برای تعیین فرمت باینری دریافتی، ویژگی binaryType شی WebSocket را روی 'blob' یا 'arraybuffer' تنظیم کنید. فرمت پیش فرض 'blob' است. (شما لازم نیست پارامتر binaryType را هنگام ارسال تراز کنید.)
// Setting binaryType to accept received binary as either 'blob' or 'arraybuffer'
connection.binaryType = 'arraybuffer';
connection.onmessage = function(e) {
console.log(e.data.byteLength); // ArrayBuffer object if binary
};
یکی دیگر از ویژگی های جدید اضافه شده WebSocket افزونه ها است. با استفاده از افزونه ها، امکان ارسال فریم های فشرده ، مالتی پلکس و غیره وجود خواهد داشت. می توانید پس از رویداد باز، پسوندهای مورد قبول سرور را با بررسی ویژگی extensions شی WebSocket بیابید. تا فوریه 2012 هنوز هیچ مشخصات برنامه افزودنی به طور رسمی منتشر نشده است.
// Determining accepted extensions
console.log(connection.extensions);
ارتباط متقابل
به عنوان یک پروتکل مدرن، ارتباطات متقاطع مستقیماً در WebSocket ایجاد می شود. در حالی که هنوز باید مطمئن شوید که فقط با مشتریان و سرورهایی که به آنها اعتماد دارید ارتباط برقرار می کنید، WebSocket ارتباط بین طرفین را در هر دامنه ای امکان پذیر می کند. سرور تصمیم می گیرد که آیا سرویس خود را در دسترس همه مشتریان قرار دهد یا فقط برای آنهایی که در مجموعه ای از دامنه های تعریف شده قرار دارند.
سرورهای پروکسی
هر فناوری جدید مجموعه جدیدی از مشکلات را به همراه دارد. در مورد WebSocket، این سازگاری با سرورهای پروکسی است که ارتباطات HTTP را در اکثر شبکه های شرکت واسطه می کند. پروتکل WebSocket از سیستم ارتقاء HTTP (که معمولاً برای HTTP/SSL استفاده می شود) برای "ارتقا" اتصال HTTP به اتصال WebSocket استفاده می کند. برخی از سرورهای پروکسی این را دوست ندارند و اتصال را قطع می کنند. بنابراین، حتی اگر یک کلاینت معین از پروتکل WebSocket استفاده کند، ممکن است امکان برقراری ارتباط وجود نداشته باشد. این موضوع بخش بعدی را مهم تر می کند :)
امروز از WebSockets استفاده کنید
WebSocket هنوز یک فناوری جوان است و به طور کامل در همه مرورگرها پیاده سازی نشده است. با این حال، امروزه میتوانید از WebSocket با کتابخانههایی استفاده کنید که هر زمان که WebSocket در دسترس نباشد، از یکی از گزینههای بازگشتی ذکر شده در بالا استفاده میکنند. کتابخانه ای که در این دامنه بسیار محبوب شده است socket.io است که با یک کلاینت و اجرای پروتکل سرور ارائه می شود و شامل موارد برگشتی می شود (socket.io هنوز از فوریه 2012 از پیام رسانی باینری پشتیبانی نمی کند). همچنین راه حل های تجاری مانند PusherApp وجود دارد که می تواند به راحتی با ارائه یک API HTTP برای ارسال پیام های WebSocket به مشتریان، در هر محیط وب ادغام شود. با توجه به درخواست HTTP اضافی، همیشه در مقایسه با WebSocket خالص سربار اضافی وجود خواهد داشت.
سمت سرور
استفاده از WebSocket یک الگوی استفاده کاملاً جدید برای برنامه های سمت سرور ایجاد می کند. در حالی که پشته های سرور سنتی مانند LAMP حول چرخه درخواست/پاسخ HTTP طراحی می شوند، اغلب با تعداد زیادی از اتصالات باز WebSocket به خوبی برخورد نمی کنند. باز نگه داشتن تعداد زیادی اتصال به طور همزمان نیاز به معماری دارد که همزمانی بالایی را با هزینه عملکرد پایین دریافت کند. چنین معماری هایی معمولاً حول محور threading یا به اصطلاح IO غیر مسدود کننده طراحی می شوند.
پیاده سازی سمت سرور
- Node.js
- جاوا
- روبی
- پایتون
- ارلنگ
- C++
- دات نت
نسخه های پروتکل
پروتکل سیمی (دست دادن و انتقال داده بین مشتری و سرور) برای WebSocket اکنون RFC6455 است. جدیدترین کروم و کروم برای اندروید کاملاً با RFC6455 از جمله پیامرسانی باینری سازگار هستند. همچنین، فایرفاکس با نسخه 11، اینترنت اکسپلورر در نسخه 10 سازگار خواهد بود. همچنان می توانید از نسخه های پروتکل قدیمی استفاده کنید، اما توصیه نمی شود زیرا آنها آسیب پذیر هستند. اگر اجرای سرور برای نسخه های قدیمی پروتکل WebSocket دارید، توصیه می کنیم آن را به آخرین نسخه ارتقا دهید.
موارد استفاده کنید
از WebSocket هر زمان که نیاز به تأخیر بسیار کم، اتصال تقریباً بیدرنگ بین مشتری و سرور دارید، استفاده کنید. به خاطر داشته باشید که این ممکن است شامل بازنگری در نحوه ساخت برنامه های کاربردی سمت سرور خود با تمرکز جدید بر فناوری هایی مانند صف رویدادها باشد. چند نمونه از موارد استفاده عبارتند از:
- بازی های آنلاین چند نفره
- برنامه های چت
- پخش زنده ورزشی
- به روز رسانی بیدرنگ جریان های اجتماعی
دموها
- Plink
- با من نقاشی کن
- Pixelatr
- بریده بریده
- جدول کلمات متقاطع آنلاین انبوه چند نفره
- سرور پینگ (استفاده شده در مثال های بالا)
- نمونه نمایش HTML5