socketio / socket.io-protocol Goto Github PK
View Code? Open in Web Editor NEWSocket.IO Protocol specification
Home Page: https://socket.io
Socket.IO Protocol specification
Home Page: https://socket.io
I have been using unity socket IO for a while, but i havent seen in the doc where it is possibel to catch and handle disconnection on the client side
I have difficulties in even understanding the notation of the protocol specification. Is that intended? If you want people to adapt the protocol to different platforms, a real specification would be very helpful. Even an RFC is easier to read than what you have here. I don't expect an answer at all, because I see that this issue is not a big concern for the socket.io implementers. If so, it would be reflected in a better documentation.
I think reverse-engineering of the protocol will be less error-prone than the docs. Hope to see some changes soon.
There should be a branch for each version of the protocol, as there are branches on the socket.io repository for the various versions. I have found it extremely frustrating to develop a client implementation without this necessary information.
Hi !
I'm working on a socket.io server implementation in rust and I use a lot your socket.io and engine.io test-suite. I have some problems with the test should ignore WebSocket connection with same sid after upgrade
though.
The implementation in the socket.io-protocol is :
const sid = await initLongPollingSession();
const socket = new WebSocket(
`${WS_URL}/socket.io/?EIO=4&transport=websocket&sid=${sid}`
);
await waitFor(socket, "open");
socket.send("2probe");
socket.send("5");
const socket2 = new WebSocket(
`${WS_URL}/socket.io/?EIO=4&transport=websocket&sid=${sid}`
);
await waitFor(socket2, "close");
The implementation in the engine.io-protocol is :
const sid = await initLongPollingSession();
const socket = new WebSocket(
`${WS_URL}/engine.io/?EIO=4&transport=websocket&sid=${sid}`
);
await waitFor(socket, "open");
socket.send("2probe");
socket.send("5");
const socket2 = new WebSocket(
`${WS_URL}/engine.io/?EIO=4&transport=websocket&sid=${sid}`
);
await waitFor(socket2, "error");
socket.send("4hello");
const { data } = await waitFor(socket, "message");
expect(data).to.eql("4hello");
In the first implementation it waits for the second socket to close whereas in the second implementation it waits for the second socket to throw an error. Therefore I have some problems testing my implementation :
First I had to make it return a 400 bad request when upgrading the second socket (to match the second implementation) but then to match the first implementation I had to gracefully close the connection (and then the second doesn't work correctly).
I suppose there is a solution to match both implementation in node but I don't know if I could do the same in rust.
Thanks for your help !
gh repo clone socketio/socket.io
Hi,
My goal is to emit a single message to a socketio server, then quit. I use polling
transport, so I do a GET
request to /socket.io?t=xxx&transport=polling
, this gives me back server response with sid
so I make another GET
to /socket.io?t=xxx&transport=polling&sid=xxx
which responsds with message �40
which, as I understand is engine.io
message (code 4), socket.io connect (code 0). Next when I repeat the GET
request with sid
, curl
waits for response, is this proper behaviour?
When I do POST
(with sid
etc) during that time in another terminal, the server sends engine.io 1
message (close).
How can I emit a message after the handshake?
This specification needs a lot of work to become a true communication protocol specification.
A protocol specification should allow at least:
A protocol is not an API, although procedures should be specified, a protocol is independent from APIs, meaning that the same protocol may be implemented with several incompatible APIs that may offer various levels of abstractions.
A reference implementation may be provided but without a proper protocol specification it is impossible to tell if the reference implementation:
Furthermore, a reference implementation includes both implementation of the protocol plus an API, making it harder to understand the protocol itself.
A protocol may have bugs, and security issues, without a specification, it is impossible to evaluate if there are such issues.
At the lower level, a protocol must specify, for each transport, the format for every packet (or message) allowed.
At the higher level, procedures explain how and when these packets are exchanged. This includes the description of responses to requests, acknowledges, retransmissions, timers, connection and reconnection procedures, procedural errors, flow control procedures, etc... State machines may be provided to document these procedures.
(chinese)我在用C实现一个Socket.io协议。但是这里的协议看不懂,代码实现也看不懂,抓包贡献下我知道的例子:
42["message"]
42["message", "message1"]
42["message", "message1", "message2"]
42["message",{"hello":"world"}]
42/hardware,["message","hello world"]
451-["level5","xxx",{"_placeholder":true,"num":0}] //这里的二进制消息变成了一个placeholder
0468656c6c6f3132333435 //前面是0x04,后面是内容hello12345
452-[{"_placeholder":true,"num":0},{"_placeholder":true,"num":1}]
0468656c6c6f3132333435 //前面是0x04,后面是内容hello12345
0468656c6c6f3132333435 //前面是0x04,后面是内容hello12345
451-/admin,["level5","xxx",{"_placeholder":true,"num":0}]
0468656c6c6f3132333435 //前面是0x04,后面是内容hello12345
I'm trying to communicate with an EIO=3
socket.io server and I'm noticing that there's this 42x number showing up in front of the subscriptions after the length:
POST https://insight.dash.org/socket.io/?EIO=3&transport=polling&t=O5WgT6e&sid=vsxjXIoH1XiRiBLwBdSW
22:423["subscribe","inv"]23:424["subscribe","sync"]75:420["subscribe","dashd/addresstxid",["XoQVXRCQ6rR9s2EKh5GDMXR3JRtKCzt9pp"]]23:421["subscribe","sync"]23:425["subscribe","sync"]
For the life of me, I cannot figure out what this is supposed to mean, and I can't seem to find any documentation referencing this protocol version, nor can I find this pattern in the current versions of reference implementations that I've looked at.
It seems like the 42x number rotates, but not in any order I can understand.
I'd love some help deciphering what's going on here.
If I upgrade client to version 3, it will fail to connect to a group of servers that I am unable to upgrade at the same time. If I upgrade server, the clients that I am unable to upgrade at the same time will fail.
I use Socket.IO between many different clients and servers. I can not upgrade everything at the same time, because I do not have all under my control and they have maintenance breaks at different times over many months.
Thus I have clients that need to be able to talk to many different versions of servers (and I have servers that are connected to by clients of different versions).
This needs protocol version discovery and use of common version supported by both ends. Should be possible at least over two consecutive versions, or what ever span of versions is needed to cover possibly a maintenance period of a year.
Could be implemented for example by client sending the version he is using for the initial request. If server does not support it, report back with versions it supports for the client to try again.
Currently, for each message check this function is called to wait for a message. However it causes a lot of failed checks because the latency of this function is quite high (because of the new event listener and the promise).
function waitFor(socket, eventType) {
return new Promise((resolve) => {
socket.addEventListener(
eventType,
(event) => {
resolve(event);
},
{ once: true }
);
});
}
It became really problematic with buffered messages. Recently I have added a flush mechanism on socketioxide to avoid flushing the websocket for each socket.io packet. Also because the engine.io connect packet is sent immediately after the websocket initialisation it may not be handled because of the same issue.
Here is an example where the waitFor
function makes the test break and a hacky solution. However this happens almost everywhere. This issue can be reproductible even with the official test server with the following command to overload a bit the nodejs event loop :
seq 10 | parallel -j 10 'npm test -- -f "should connect then disconnect from a custom namespace"; echo '
it("should connect then disconnect from a custom namespace", async () => {
const socket = await initSocketIOConnection();
await waitFor(socket, "message"); // ping
// Create a waiting promise *before* sending the trigger packet "40/custom" makes the trick
const handshakeHandler = waitForPackets(socket, 2);
socket.send("40/custom");
// await waitFor(socket, "message"); // Socket.IO handshake
// await waitFor(socket, "message"); // auth packet
await handshakeHandler;
socket.send("41/custom");
socket.send('42["message","message to main namespace"]');
const { data } = await waitFor(socket, "message");
expect(data).to.eql('42["message-back","message to main namespace"]');
});
I didn't find any good solution to propose a PR. If there is no solution to this issue. I may consider rewriting the test suite in another language to avoid event loop issues. Maybe @darrachequesne you have an idea ?
handshake returns this:
00000000 00 01 01 01 ff 30 7b 22 73 69 64 22 3a 22 30 6a 0{"sid":"0j
00000010 57 4b 7a 6d 79 38 69 45 37 71 42 5a 49 4a 41 41 WKzmy8iE7qBZIJAA
00000020 41 65 22 2c 22 75 70 67 72 61 64 65 73 22 3a 5b Ae","upgrades":[
00000030 22 77 65 62 73 6f 63 6b 65 74 22 2c 22 66 6c 61 "websocket","fla
00000040 73 68 73 6f 63 6b 65 74 22 5d 2c 22 70 69 6e 67 shsocket"],"ping
00000050 49 6e 74 65 72 76 61 6c 22 3a 32 35 30 30 30 2c Interval":25000,
00000060 22 70 69 6e 67 54 69 6d 65 6f 75 74 22 3a 36 30 "pingTimeout":60
00000070 30 30 30 7d 000}
event looks like this:
00000000 00 02 ff 34 30 00 02 07 ff 34 32 5b 22 65 76 65 40 42["eve
00000010 6e 74 22 2c 7b 22 73 6f 6d 65 22 3a 22 64 61 74 nt",{"some":"dat
00000020 61 22 7d 5d a"}]
where do they come from and why are they there? (payload?)
do I have to split the response by 0xFF
to get the packets?
thanks
The protocol is not very clear on how it exactly works.
As Example this issue. socketio/socket.io#1894
Nowhere is described that upgrading the connection needs a 5 to be sent over the websocket to complete it before other messages are sent.
connecting to a namespace requires a 40.
However that number is not explained over here.
4 means error
0 means connect
The documentation for the handshake process should be documented.
Originally requested here: socketio/socket.io#1577
Would it be possible to add a test-suite
for the V3 protocol? I'm adding support for the V3 protocol to socketioxide (an implementation in Rust) and it would definitely help to test the correctness of the implementation without too much guesswork or possible oversight.
My application is in PHP, and due to the lack of clients for SocketIO with support for V4.0 I am creating internal functions that connect via cURL to emit events from my application to the Socket.IO server that I have.
So far everything is going fine, when I just need to set the server event name and a basic sent value.
Like the example below:
CURLOPT_POSTFIELDS => '42["eventNameOnServer","My Value."]'
My problem is occurring when I try to send a JSON, such as {"id":1,"value":"String"}.
CURLOPT_POSTFIELDS => '42["eventNameOnServer","{\\"id\\":1,\\"value\\":\\"String\\"}."]'
For double quotes I realized that I have to always put two \ in front of the quote to be accepted by SocketIO. Are there any other rules that must be followed when performing this procedure?
To help illustrate the protocol can you update the readme with a snippet of packets that represents a successful connection to the server and send?
CONNECT
ACK
{"sid":"YasdL-sPEI9Ii5EzAAeq","upgrades":[],"pingInterval":25000,"pingTimeout":60000}
....
I use socket.io with xhr-polling. I have to manipulate the content, but I cannot understand one part of the protocol.
If I send a broadcast message (event), I see that the message starts with 42. 4 means it's an event, 2 means it's a message (engine.io).
But, if I use xhr-polling, instead of websocket, I see some unicode characters at the start of the packet, such as: \u0000\u0003\u0002\u0004�42[...PACKET...]
What do these unicode characters mean? What is that question before 42? I don't see any related documentations, but I do see that the message when it's an xhr-polling transport is binary encoded. BUT, how, and in what structure?
I tried to figure out with this: http://unicode-table.com/en/
But I've not found any good answer :(
Can you explain what is your solution for user authentication over socket.io?
docs link to https://socket.io/docs/namespaces/ but it is broken
gh repo clone socketio/socket.io
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.