3

Note: The closest question I have found to mine is this one, but the answer is to send data via a proxy function that waits for the readyState to be 1. This is not a duplicate of that question though the titles are very similar; I know my issue lies in my server not passing data back to the client, but I don't know what to pass.

Details:

I have a TCP Listener defined in my server program as a New TcpListener(ipAd, 8001) and I wrote a client program as a New TcpClient() to connect to the server. These programs work as intended, where as soon as the connection is made, the client is ready to send data to the server.

After I completed the client and server, I began working on a web interface to act as the client, so I could send data to the socket from any device. Here is the javascript code for the websocket:

    console.log("Attempting to connect...");

    ws = new WebSocket('ws://192.168.0.10:8001/');

    ws.onopen = function(msg) {
        console.log('Connection successfully opened');
    };

    ws.onmessage = function(msg) {
        console.log(msg);
    };

    ws.onclose = function(msg) {
        console.log("Closed.");
    }

    ws.error = function(err){
        console.log(err);
    }

When I load the webpage, I see in my server console app that the connection is made. Here is the output:

GET / HTTP/1.1
Host: 192.168.0.10:8001
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-
cache
Upgrade: websocket
Origin: null
Sec-WebSocket-Version: 13
User-Agent: Mozilla/5.0 (Windows
 NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36
Accept-Enc
oding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Sec-WebSocket-Key: key_here
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

So clearly the HTTP headers are sent and received; however, my server (currently) does not send anything back to the client, so when I try to issue ws.send("test"); from the websocket, I receive an error in console:

Uncaught InvalidStateError: Failed to execute 'send' on 'WebSocket': Still in CONNECTING state.

My Question: What do I need to send back to the client from my server to complete the handshake, so that I can send data with ws.send();?

Community
  • 1
  • 1
Chad
  • 1,531
  • 3
  • 20
  • 46

1 Answers1

4

You need to implement the server-side of a webSocket (or use a webSocket library that does that for you). Here's one sample implementation in VB. And a similar question with sample code.

A webSocket connection works like this:

  1. Client makes http request to server with custom header requesting upgrade to webSocket protocol

  2. Server responds that the upgrade to webSocket is OK and with a randomly generated security key.

  3. After the server sends the response and the client receives it, then both sides switch to the webSocket data frame format for future data.

  4. In addition, there are some mandatory messages that must be supported such as ping and pong to support the keepalive heartbeat that the client will use to know if the connection is still alive.

See this article for example responses and a description of the webSocket data frame format.

In addition, browsers enforce same-origin restrictions by default so if you are trying to connect from a browser to a different origin than the web page that the Javascript is in, then you will need the appropriate CORS headers from your server to enable the cross origin connection.


Here's a sample connection:

Client sends this:

GET /chat HTTP/1.1
Host: example.com:8000
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

Server responds with this:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

Then, data frames look like this:

0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len |    Extended payload length    |
|I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
|N|V|V|V|       |S|             |   (if payload len==126/127)   |
| |1|2|3|       |K|             |                               |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
|     Extended payload length continued, if payload len == 127  |
+ - - - - - - - - - - - - - - - +-------------------------------+
|                               |Masking-key, if MASK set to 1  |
+-------------------------------+-------------------------------+
| Masking-key (continued)       |          Payload Data         |
+-------------------------------- - - - - - - - - - - - - - - - +
:                     Payload Data continued ...                :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
|                     Payload Data continued ...                |
+---------------------------------------------------------------+

And, of course, the webSocket RFC official specification is here.

Community
  • 1
  • 1
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • 1
    Your link to the Mozilla sample code worked, but it needed a quick change. `Dim FRRROPCODE As Byte()` needed to be changed to just `Byte` instead of being an array. Also "Recieved" is spelled incorrectly in that code. – Chad Feb 04 '15 at 20:05
  • Tried logging in to edit it but Mozilla won't accept my credentials :\ – Chad Feb 04 '15 at 20:05