10

I'm trying to use elephant.io to send event from my PHP script to my nodejs server. Performing tests with this library I've noticed that the handshake was not happening as expected.

After reading the specs about client-server handshake with socket.io, I've tested a simple handshake request to my nodejs server:

POST "http://acme.local:3700/socket.io/1"

But this is returning the following JSON message:

{
    "code": 0,
    "message": "Transport unknown"
}

I'm not sure if this error is due to the version of socket.io I'm using (v1.0.2) or if the handshake request is simply malformed.

maxwell2022
  • 2,698
  • 4
  • 38
  • 57
  • I recommend you to have a look at [this github ticket](https://github.com/Automattic/socket.io/issues/1577#issuecomment-46275713) where they got a bit further than me – maxwell2022 Jun 19 '14 at 00:45

3 Answers3

15

The problem is socket.io v1.0.x revamped its transport layer. In 0.9.x, socket.io tries to establish a websocket connection firstly and fall back to polling if websocket is blocked, timeout, etc. So you can download a websocket configuration string like "sid:interval_time:timeout_time:..." from schema://addr:port/socket.io/1/.

However, in v.1.0.x, the client has to establish a polling transportation first, which is widely supported, then upgrade to websocket. And the transport configuration is formatted in json via: schema://addr:port/socket.io/?transport=polling. The json object looks like {"sid":"xxx", "upgrade":["websocket",..],"pingInterval":xxx,"pingTimeout":xxx}.

So any client works for v0.9.x can't communicate with v1.0.x. There is a temporary fix for elephant.io: https://github.com/Wisembly/elephant.io/pull/53/files#diff-8f2bc4c2d1b3889bc393b67f296edbc5R97 . However I can't get it to work.

Presumably all 3rd-party clients for socket.io v1.0.x nowadays are full-port of its JavaScript code. I tried to fix socketio4net according to the elephant.io post above but failed.

Update on 08/26.

Here's what I got:

How to communicate with socket.io v1.0 server:

  1. GET http[s]://host:port/socket.io/?transport=polling

  2. Server responds a JSON config string in response body with some unknown characters as header.

    Warning for c-style char* useres: this string begins with '\0'.

    The string looks like: \0xxxx {"sid":"xxx", "upgrades":["websocket","polling",..], pingInterval:xxxx, pingTimeout:xxxx}.

    sid: seesion id for websocket connection.

    upgrades: available transport method. Please make sure "websocket" is one of them.

    pingInterval & pingTimeout: ping server every pingInterval and check for pong within pingTimeout.

  3. Establish websocket connection at ws[s]://host:port/socket.io/?transport=websocket&sid=sid

  4. Send string "52" to socket.io server upon successful connection.

  5. Listen on server message, waiting for string "40" to confirm websocket link between client and server.

  6. Send any other commands you setup on sever.

Note:

v1.0 changed its message transport format to engine.io_type + socket.io_type + real_message_in_json. (I don't know where endpoint in v0.9 kicks in.)

engine.io message type:

  • open =0
  • close =1
  • ping =2
  • pong =3
  • message =4
  • upgrade =5
  • noop =6

socket.io message type:

  • connect = 0
  • disconnect = 1
  • event = 2
  • ack = 3
  • error = 4
  • binary_event = 5
  • binary_ack = 6

So, "52" means UPGRADE_EVENT and "40" is MESSAGE_CONNECT. Typically, server messages start with "42", which is MESSAGE_EVENT. PING and PONG don't require a socket.io message. I wonder if UPGRADE works like that too.

Get a working websocket client and you are good to go!

P.S. elephant.io 3.0 is on the way, which supports v1.0.

neutrino
  • 159
  • 1
  • 3
  • Hi, I have tried your suggestion. I have established the connection but cannot fire the event on the server. I send with the 42 but i think server could not get the message. – Ozan Deniz Dec 25 '14 at 13:48
  • 1
    @Ozan 42 works as the head code for server to understand your message. Functional information need to be appended.. Example: if the js code you are working with is `socket.emit('foo', 'bar');`, you shall send `"42["foo", "bar"]"`. Good luck! – neutrino Jan 22 '15 at 02:33
  • Yep you are right. I just couldn't give correct json format to the server. Now it is working correctly. Thanks for the answer. It helps me too much to set up. This json format worked perfect: 42["event",{"msg":"test"}] – Ozan Deniz Jan 22 '15 at 08:17
  • You are great!! Your detailed answer very helped to "upgrade" standard `ratchetphp/Pawl` websocket client to socket.io-websocket client, that excellently works with socket.io-websocket servers. – FlameStorm May 26 '20 at 17:53
3

Reverting to socket.io v0.9.x fix the issue. Apparently the handshake changed in v1.0.x but I cannot find any documentation yet

maxwell2022
  • 2,698
  • 4
  • 38
  • 57
0

I got the same problem and this is my solution: io.connect('localhost', {transport:'polling'});