Websocket server: onopen function on the web socket is never called
Asked Answered
B

3

63

I'm trying to implement a C# web socket server, but its giving me a few troubles. I'm running a webserver(ASP.NET) to host the page with the javascript and the web socket server is implemented as a C# console application.

I'm able to detect the connection attempt from the client (chrome running the javascript) and also to retrieve the handshake from the client. But the client doesn't seem to accept the handshake I'm sending back (the onopen function on the web socket is never called).

I've been reading the The Web Socket protocol and I can't see what I'm doing wrong. Heres a bit of the server code:

Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
IPEndPoint ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8181);
listener.Bind(ep);
listener.Listen(100);
Console.WriteLine("Wainting for connection...");
Socket socketForClient = listener.Accept();
if (socketForClient.Connected)
{
    Console.WriteLine("Client connected");
    NetworkStream networkStream = new NetworkStream(socketForClient);
    System.IO.StreamWriter streamWriter = new System.IO.StreamWriter(networkStream);
    System.IO.StreamReader streamReader = new System.IO.StreamReader(networkStream);

    //read handshake from client:
    Console.WriteLine("HANDSHAKING...");
    char[] shake = new char[255];
    streamReader.Read(shake, 0, 255);

    string handshake =
       "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" +
       "Upgrade: WebSocket\r\n" +
       "Connection: Upgrade\r\n" +
       "WebSocket-Origin: http://localhost:8080\r\n" +
       "WebSocket-Location: ws://localhost:8181\r\n" +
       "\r\n";

    streamWriter.Write(handshake);
    streamWriter.Flush();

I'm running to web server on port 8080 and the web socket server on port 8181, both on my localhost.

I've tried sending the handshake in different encodings (ASCII, bytes and Hex) but this doesn't seem to make a difference. The connection is never fully established. The javascript looks like this:

var ws;
var host = 'ws://localhost:8181';
debug("Connecting to " + host + " ...");
try {
 ws = new WebSocket(host);
} catch (err) {
 debug(err, 'error');
}
ws.onopen = function () {
 debug("connected...", 'success');
};
ws.onclose = function () {
 debug("Socket closed!", 'error');
};
ws.onmessage = function (evt) {
 debug('response: ' + evt, 'response');
};

I'm guessing that the error lies in the C# server as chrome is sending the information as it should, but as a said the onopen function is never called.

So my question in short: Has any of you ever accomplished this - and if yes, how did you do it? And of cause: Do you see any apparent errors in the code (hope thats not to much to ask)

Beerbohm answered 6/2, 2010 at 3:28 Comment(1)
You may want to use Fleck, available on NuGet: nuget.org/packages/FleckPeppie
A
50

Probably it's an encoding issue. Here's a working C# server I wrote:

class Program
{
    static void Main(string[] args)
    {
        var listener = new TcpListener(IPAddress.Loopback, 8181);
        listener.Start();
        using (var client = listener.AcceptTcpClient())
        using (var stream = client.GetStream())
        using (var reader = new StreamReader(stream))
        using (var writer = new StreamWriter(stream))
        {
            writer.WriteLine("HTTP/1.1 101 Web Socket Protocol Handshake");
            writer.WriteLine("Upgrade: WebSocket");
            writer.WriteLine("Connection: Upgrade");
            writer.WriteLine("WebSocket-Origin: http://localhost:8080");
            writer.WriteLine("WebSocket-Location: ws://localhost:8181/websession");
            writer.WriteLine("");
        }
        listener.Stop();
    }
}

And the corresponding client hosted on localhost:8080:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <script type="text/javascript">
      var socket = new WebSocket('ws://localhost:8181/websession');
      socket.onopen = function() {
        alert('handshake successfully established. May send data now...');
      };
      socket.onclose = function() {
        alert('connection closed');
      };
    </script>
  </head>
  <body>
  </body>
</html>

This example only establishes the handshake. You will need to tweak the server in order to continue accepting data once the handshake has been established.

Ataliah answered 6/2, 2010 at 10:7 Comment(4)
Thanks! Turns out it was the WebSocket-Location part of the handshake that was giving me trouble. Apparently it can't be just 'ws://localhost:8181'. After changing it to 'ws://localhost:8181/something' and changing the host in the javascript to the same thing - it worked.Beerbohm
Thanks for the post. I was attempting this with Chrome + a static html file and had to change the origin to prevent the browser from immediately disconnecting: writer.WriteLine("WebSocket-Origin: file://");Bohman
@Darin Your code is working fine. It didn't work when I removed that "using" and declared that "writer" as usual. The thing is the writer didn't write back to the client. Can you explain this?Zulemazullo
@Darin I found the answer for my question. The answer is "writer.Flush()"Zulemazullo
E
24

Please use UTF8 encoding to send text message.

There is an open source websocket server which is implemented by C#, you can use it directly.

http://superwebsocket.codeplex.com/

It's my open source project!

Expressly answered 8/12, 2010 at 2:20 Comment(1)
Now, SuperWebSocket also contains a WebSocket client implementation!Expressly
S
3

The .NET Framework 4.5 introduces support for WebSockets in Windows Communication Foundation. WebSockets is an efficient, standards-based technology that enables bidirectional communication over the standard HTTP ports 80 and 443. The use of the standard HTTP ports allow WebSockets to communicate across the web through intermediaries. Two new standard bindings have been added to support communication over a WebSocket transport. NetHttpBinding and NetHttpsBinding. WebSockets-specific settings can be configured on the HttpTransportBinding element by accessing the WebSocketSettings property.

I think it still uses SOAP though

http://msdn.microsoft.com/en-us/library/hh674271(v=vs.110).aspx

Sealer answered 24/5, 2012 at 14:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.