Ana içeriğe geç

Socket.IO protokolü

Bu belge, Socket.IO protokolünün 5. sürümünü tanımlamaktadır.

Bu belgenin kaynağını buradan bulabilirsiniz.

İçindekiler

  • Giriş
  • Değişim protokolü
    • Bir ad alanına bağlanma
    • Veri gönderme ve alma
    • Onay
    • Bir ad alanından bağlantıyı kesme
  • Paket kodlaması
    • Format
    • Örnekler
      • Bir ad alanına bağlanma
      • Veri gönderme ve alma
      • Onay
      • Bir ad alanından bağlantıyı kesme
  • Örnek oturum
  • Tarihçe
    • v5 ile v4 arasındaki fark
    • v4 ile v3 arasındaki fark
    • v3 ile v2 arasındaki fark
    • v2 ile v1 arasındaki fark
    • İlk revizyon
  • Test takımı

Giriş

Socket.IO protokolü, bir istemci ve bir sunucu arasında full-duplex ve düşük gecikmeli iletişim sağlar.

Bu, WebSocket ve HTTP uzun süreli istekleriyle düşük seviyeli işleri yöneten Engine.IO protokolü üzerine inşa edilmiştir.

Socket.IO protokolü aşağıdaki özellikleri ekler:

  • çoklama (Socket.IO jargonunda "ad alanı" olarak adlandırılır)
ipucu

JavaScript API'si ile örnek:

Sunucu

// ad alanını tanımlama
const namespace = io.of("/admin");
// ad alanına bağlantıyı işleme
namespace.on("connection", (socket) => {
// ...
});

İstemci

// ana ad alanına erişme
const socket1 = io();
// "/admin" ad alanına erişme (aynı WebSocket bağlantısıyla)
const socket2 = io("/admin");
// ad alanına bağlantıyı işleme
socket2.on("connect", () => {
// ...
});
  • paketlerin onaylanması

JavaScript API'si ile örnek:

// bir tarafta
socket.emit("hello", "foo", (arg) => {
console.log("alındı", arg);
});

// diğer tarafta
socket.on("hello", (arg, ack) => {
ack("bar");
});
bilgi

Değişim protokolü

Bir Socket.IO paketi aşağıdaki alanları içerir:

  • bir paket türü (tam sayı)
  • bir ad alanı (metin)
  • isteğe bağlı, bir yük (Nesne | Dizi)
  • isteğe bağlı, bir onay kimliği (tam sayı)

Mevcut paket türlerinin listesi:

TürIDKullanım
BAĞLAN0Bir ad alanına bağlanma sırasında kullanılır.
BAĞLANTIKESİ1Bir ad alanından bağlantıyı kesme sırasında kullanılır.
OLAY2Diğer tarafa veri gönderme için kullanılır.
ONAY3Bir olayı onaylamak için kullanılır.
BAĞLANTI_HATASI4Bir ad alanına bağlanma sırasında kullanılır.
İKİLİ_OLAY5Diğer tarafa ikili veri gönderme için kullanılır.
İKİLİ_ONAY6Bir olayı onaylamak için kullanılır (yanıt ikili veri içerir).

Bir ad alanına bağlanma

Bir Socket.IO oturumunun başlangıcında, istemci bir BAĞLAN paketi göndermelidir:

Sunucu, ya:

  • başarılı bir bağlantı durumunda, yük içinde oturum kimliği ile bir BAĞLAN paketi ile yanıt vermelidir
  • ya da bağlantının izin verilmediği durumlarda bir BAĞLANTI_HATASI paketi ile yanıt vermelidir
İSTEMCİ                                                      SUNUCU

│ ───────────────────────────────────────────────────────► │
│ { type: BAĞLAN, namespace: "/" } │
│ ◄─────────────────────────────────────────────────────── │
│ { type: BAĞLAN, namespace: "/", data: { sid: "..." } } │

Eğer sunucu öncelikle bir BAĞLAN paketi almazsa, bağlantıyı derhal kapatmalıdır.

Bir istemci aynı anda birden fazla ad alanına bağlanabilir, aynı WebSocket bağlantısıyla.

Örnekler:

  • ana ad alanı ile ("/" olarak adlandırılır)
İstemci > { type: BAĞLAN, namespace: "/" }
Sunucu > { type: BAĞLAN, namespace: "/", data: { sid: "wZX3oN0bSVIhsaknAAAI" } }
  • bir özel ad alanı ile
İstemci > { type: BAĞLAN, namespace: "/admin" }
Sunucu > { type: BAĞLAN, namespace: "/admin", data: { sid: "oSO0OpakMV_3jnilAAAA" } }
  • ek bir yük ile
İstemci > { type: BAĞLAN, namespace: "/admin", data: { "token": "123" } }
Sunucu > { type: BAĞLAN, namespace: "/admin", data: { sid: "iLnRaVGHY4B75TeVAAAB" } }
  • bağlantının reddedildiği durumda
İstemci > { type: BAĞLAN, namespace: "/" }
Sunucu > { type: BAĞLANTI_HATASI, namespace: "/", data: { message: "Yetkisiz" } }

Veri gönderme ve alma

Bir ad alanına bağlanma sağlandıktan sonra, istemci ve sunucu veri alışverişine başlayabilir:

İSTEMCİ                                                      SUNUCU

│ ───────────────────────────────────────────────────────► │
│ { type: OLAY, namespace: "/", data: ["foo"] } │
│ │
│ ◄─────────────────────────────────────────────────────── │
│ { type: OLAY, namespace: "/", data: ["bar"] } │

Yük zorunludur ve boş olmayan bir dizi olmalıdır. Aksi takdirde, alıcı bağlantıyı kapatmalıdır.

Örnekler:

  • ana ad alanı ile
İstemci > { type: OLAY, namespace: "/", data: ["foo"] }
  • özel bir ad alanı ile
Sunucu > { type: OLAY, namespace: "/admin", data: ["bar"] }
  • ikili veri ile
İstemci > { type: İKİLİ_OLAY, namespace: "/", data: ["baz", <Buffer <01 02 03 04>> ] }

Onay

Gönderen, alıcıdan bir onay talep etmek için bir olayı ID'si ekleyebilir:

İSTEMCİ                                                      SUNUCU

│ ───────────────────────────────────────────────────────► │
│ { type: OLAY, namespace: "/", data: ["foo"], id: 12 } │
│ ◄─────────────────────────────────────────────────────── │
│ { type: ONAY, namespace: "/", data: ["bar"], id: 12 } │

Alıcı, aynı olay ID'si ile bir ONAY paketi ile yanıt vermelidir.

Yük zorunludur ve bir dizi (boş olabilir) olmalıdır.

Örnekler:

  • ana ad alanı ile
İstemci > { type: OLAY, namespace: "/", data: ["foo"], id: 12 }
Sunucu > { type: ONAY, namespace: "/", data: [], id: 12 }
  • özel bir ad alanı ile
Sunucu > { type: OLAY, namespace: "/admin", data: ["foo"], id: 13 }
İstemci > { type: ONAY, namespace: "/admin", data: ["bar"], id: 13 }
  • ikili veri ile
İstemci > { type: İKİLİ_OLAY, namespace: "/", data: ["foo", <buffer <01 02 03 04> ], id: 14 }
Sunucu > { type: ONAY, namespace: "/", data: ["bar"], id: 14 }

veya

Sunucu > { type: OLAY, namespace: "/", data: ["foo" ], id: 15 }
İstemci > { type: İKİLİ_ONAY, namespace: "/", data: ["bar", <buffer <01 02 03 04>], id: 15 }

Bir ad alanından bağlantıyı kesme

Herhangi bir zaman, bir taraf BAĞLANTIKESİ paketi göndererek bir ad alanı ile bağlantıyı sonlandırabilir:

İSTEMCİ                                                      SUNUCU

│ ───────────────────────────────────────────────────────► │
│ { type: BAĞLANTIKESİ, namespace: "/" } │

Diğer taraftan bir yanıt beklenmez. Düşük seviyeli bağlantı, istemci başka bir ad alanına bağlıysa canlı tutulabilir.

Paket kodlaması

Bu bölüm, Socket.IO sunucusu ve istemcisinde dahil edilen varsayılan parser tarafından kullanılan kodlamayı detaylandırmaktadır ve kaynak buradan bulunabilir.

JavaScript sunucu ve istemci uygulamaları ayrıca, farklı avantajlara sahip özel parser'ları destekler ve belirli uygulama türleri için faydalı olabilir. Lütfen socket.io-json-parser veya socket.io-msgpack-parser örneklerine bakın.

Ayrıca, her Socket.IO paketinin bir Engine.IO message paketi olarak gönderildiğini unutmayın (daha fazla bilgi burada), dolayısıyla kodlanan sonuç, ağ üzerinden gönderilirken "4" karakteri ile ön eklenir (HTTP uzun süreli istekleriyle, ya da WebSocket çerçevesinde).

Format

<paket türü>[<# ikili ek>][<ad alanı>,][<onay id>][JSON-stringified yük ikili olmadan]

+ ikili ekler çıkarıldı

Not: ad alanı sadece ana ad alanından (/) farklıysa dahil edilir.

Örnekler

Bir ad alanına bağlanma

  • ana ad alanı ile

Paket

{ type: BAĞLAN, namespace: "/" }

Kodlanmış

0
  • özel bir ad alanı ile

Paket

{ type: BAĞLAN, namespace: "/admin", data: { sid: "oSO0OpakMV_3jnilAAAA" } }

Kodlanmış

0/admin,{"sid":"oSO0OpakMV_3jnilAAAA"}
  • bağlantının reddedildiği durumda

Paket

{ type: BAĞLANTI_HATASI, namespace: "/", data: { message: "Yetkisiz" } }

Kodlanmış

4{"message":"Yetkisiz"}

Veri gönderme ve alma

  • ana ad alanı ile

Paket

{ type: OLAY, namespace: "/", data: ["foo"] }

Kodlanmış

2["foo"]
  • özel bir ad alanı ile

Paket

{ type: OLAY, namespace: "/admin", data: ["bar"] }

Kodlanmış

2/admin,["bar"]
  • ikili veri ile

Paket

{ type: İKİLİ_OLAY, namespace: "/", data: ["baz", <Buffer <01 02 03 04>> ] }

Kodlanmış

51-["baz",{"_placeholder":true,"num":0}]

+ <Buffer <01 02 03 04>>
  • birden fazla ek ile

Paket

{ type: İKİLİ_OLAY, namespace: "/admin", data: ["baz", <Buffer <01 02>>, <Buffer <03 04>> ] }

Kodlanmış

52-/admin,["baz",{"_placeholder":true,"num":0},{"_placeholder":true,"num":1}]

+ <Buffer <01 02>>
+ <Buffer <03 04>>

Lütfen unutmayın ki her Socket.IO paketi, bir Engine.IO message paketi içinde sarılır, bu nedenle ağ üzerinde gönderilirken "4" karakteri ile ön eklenir.

Örnek: { type: OLAY, namespace: "/", data: ["foo"] } 42["foo"] olarak gönderilecektir.

Onay

  • ana ad alanı ile

Paket

{ type: OLAY, namespace: "/", data: ["foo"], id: 12 }

Kodlanmış

212["foo"]
  • özel bir ad alanı ile

Paket

{ type: ONAY, namespace: "/admin", data: ["bar"], id: 13 }

Kodlanmış

3/admin,13["bar"]`
  • ikili veri ile

Paket

{ type: İKİLİ_ONAY, namespace: "/", data: ["bar", <Buffer <01 02 03 04>>], id: 15 }

Kodlanmış

61-15["bar",{"_placeholder":true,"num":0}]

+ <Buffer <01 02 03 04>>

Bir ad alanından bağlantıyı kesme

  • ana ad alanı ile

Paket

{ type: BAĞLANTIKESİ, namespace: "/" }

Kodlanmış

1
  • özel bir ad alanı ile
{ type: BAĞLANTIKESİ, namespace: "/admin" }

Kodlanmış

1/admin,

Örnek oturum

Engine.IO ve Socket.IO protokollerini birleştirirken ağ üzerinde gönderilenlerin bir örneği.

  • İstek n°1 (açık paket)
GET /socket.io/?EIO=4&transport=polling&t=N8hyd6w
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=UTF-8
0{"sid":"lv_VI97HAXpY6yYWAAAC","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":5000,"maxPayload":1000000}

Detaylar:

0           => Engine.IO "açık" paket türü
{"sid":... => Engine.IO el sıkışma verileri

Not: t sorgu parametresi, isteğin tarayıcı tarafından önbelleğe alınmadığından emin olmak için kullanılır.

  • İstek n°2 (ad alanı bağlantı isteği):
POST /socket.io/?EIO=4&transport=polling&t=N8hyd7H&sid=lv_VI97HAXpY6yYWAAAC
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=UTF-8
40

Detaylar:

4           => Engine.IO "mesaj" paket türü
0 => Socket.IO "BAĞLAN" paket türü
  • İstek n°3 (ad alanı bağlantı onayı)
GET /socket.io/?EIO=4&transport=polling&t=N8hyd7H&sid=lv_VI97HAXpY6yYWAAAC
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=UTF-8
40{"sid":"wZX3oN0bSVIhsaknAAAI"}
  • İstek n°4

socket.emit('hey', 'Jude') sunucuda çalıştırıldığında:

GET /socket.io/?EIO=4&transport=polling&t=N8hyd7H&sid=lv_VI97HAXpY6yYWAAAC
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=UTF-8
42["hey","Jude"]

Detaylar:

4           => Engine.IO "mesaj" paket türü
2 => Socket.IO "OLAY" paket türü
[...] => içerik
  • İstek n°5 (mesaj çıktı)

socket.emit('hello'); socket.emit('world'); istemcide çalıştırıldığında:

POST /socket.io/?EIO=4&transport=polling&t=N8hzxke&sid=lv_VI97HAXpY6yYWAAAC
> Content-Type: text/plain; charset=UTF-8
42["hello"]\x1e42["world"]
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=UTF-8
ok

Detaylar:

4           => Engine.IO "mesaj" paket türü
2 => Socket.IO "OLAY" paket türü
["hello"] => 1. içerik
\x1e => ayırıcı
4 => Engine.IO "mesaj" paket türü
2 => Socket.IO "OLAY" paket türü
["world"] => 2. içerik
  • İstek n°6 (WebSocket yükseltmesi)
GET /socket.io/?EIO=4&transport=websocket&sid=lv_VI97HAXpY6yYWAAAC
< HTTP/1.1 101 Protocols Switching

WebSocket çerçeveleri:

< 2probe                                        => Engine.IO probe talebi
> 3probe => Engine.IO probe yanıtı
> 5 => Engine.IO "yükseltme" paket türü
> 42["hello"]
> 42["world"]
> 40/admin, => yönetici ad alanına erişim talebi (Socket.IO "BAĞLAN" paketi)
< 40/admin,{"sid":"-G5j-67EZFp-q59rADQM"} => yönetici ad alanına erişim izni
> 42/admin,1["tellme"] => onay ile Socket.IO "OLAY" paketi
< 461-/admin,1[{"_placeholder":true,"num":0}] => Socket.IO "İKİLİ_ONAY" paketi, yer tutucu ile
< <ikili> => ikili ek (sonraki çerçevede gönderilir)
... bir süre mesaj olmadan sonra
> 2 => Engine.IO "ping" paket türü
< 3 => Engine.IO "pong" paket türü
> 1 => Engine.IO "close" paket türü

Tarihçe

v5 ile v4 arasındaki fark

Socket.IO protokolünün 5. revizyonu (mevcut) Socket.IO v3 ve üzeri sürümlerde kullanılmaktadır (v3.0.0 Kasım 2020'de yayınlandı).

Bu, Engine.IO protokolünün 4. revizyonu üzerine inşa edilmiştir (bu nedenle EIO=4 sorgu parametresi).

Değişikliklerin listesi:

  • varsayılan ad alanına örtük bağlantıyı kaldırma

Önceki sürümlerde, bir istemci, başka bir ad alanına erişim talep etse bile her zaman varsayılan ad alanına bağlıydı.

Bu artık böyle değil, istemci her durumda bir BAĞLAN paketi göndermelidir.

Commitler: 09b6f23 (sunucu) ve 249e0be (istemci).

  • ERROR ifadesini BAĞLANTI_HATASI olarak yeniden adlandırma

Anlamı ve kod numarası (4) değiştirilmemiştir: bu paket türü hala bir ad alanına bağlantının reddedildiğinde sunucu tarafından kullanılmaktadır. Ancak, ismin daha açıklayıcı olduğunu düşünüyoruz.

Commitler: d16c035 (sunucu) ve 13e1db7c (istemci).

  • BAĞLAN paketi artık bir yük içerebilir

İstemci, kimlik doğrulama/izin amaçları için bir yük gönderebilir. Örnek:

{
"type": 0,
"nsp": "/admin",
"data": {
"token": "123"
}
}

Başarı durumunda, sunucu bir yükle Socket kimliğini yanıt olarak döner. Örnek:

{
"type": 0,
"nsp": "/admin",
"data": {
"sid": "CjdVH4TQvovi1VvgAC5Z"
}
}

Bu değişiklik, Socket.IO bağlantısının kimliğinin, HTTP isteklerinin sorgu parametrelerinde bulunan düşük seviyeli Engine.IO bağlantısının kimliğinden farklı olacağı anlamına gelir.

Commitler: 2875d2c (sunucu) ve bbe94ad (istemci).

  • BAĞLANTI_HATASI paketinin yükü artık düz bir dize yerine bir nesnedir

Commitler: 54bf4a4 (sunucu) ve 0939395 (istemci).

v4 ile v3 arasındaki fark

Socket.IO protokolünün 4. revizyonu Socket.IO v1'de (v1.0.3 Haziran 2014'te yayınlandı) ve v2'de (v2.0.0 Mayıs 2017'de yayınlandı).

Revizyonun detayları burada bulunabilir: https://github.com/socketio/socket.io-protocol/tree/v4

Bu, Engine.IO protokolünün 3. revizyonu üzerine inşa edilmiştir (bu nedenle EIO=3 sorgu parametresi).

Değişikliklerin listesi:

  • bir İKİLİ_ONAY paket türü ekleme

Daha önce, bir ONAY paketi her zaman ikili nesneler içerebilecek şekilde değerlendirilmişti, bu da böyle nesneler için yinelemeli arama yapılıp yapılmadığına bakılmaksızın, performansı etkileyebiliyordu.

Referans: https://github.com/socketio/socket.io-parser/commit/ca4f42a922ba7078e840b1bc09fe3ad618acc065

v3 ile v2 arasındaki fark

Socket.IO protokolünün 3. revizyonu, Socket.IO v1'in ilk sürümlerinde (socket.io@1.0.0...1.0.2) kullanılmıştır (Mayıs 2014'te yayınlandı).

Revizyonun detayları burada bulunabilir: https://github.com/socketio/socket.io-protocol/tree/v3

Değişikliklerin listesi:

  • ikili nesneleri içeren paketleri kodlamak için msgpack kullanımını kaldırma (bkz. 299849b)

v2 ile v1 arasındaki fark

Değişikliklerin listesi:

  • bir İKİLİ_OLAY paket türü ekleme

Bu, Socket.IO 1.0'a doğru yapılan çalışmalarda, ikili nesneler için destek eklemek amacıyla eklenmiştir. İKİLİ_OLAY paketleri msgpack ile kodlanmıştır.

İlk revizyon

Bu ilk revizyon, Engine.IO protokolü (WebSocket / HTTP uzun süreli istekler, kalp atışı ile düşük seviyeli işler) ve Socket.IO protokolü arasındaki ayrışmanın sonucuydu. Hiçbir Socket.IO sürümünde dahil edilmemiştir, ancak sonraki iterasyonlar için bir temel hazırlamıştır.