2

I'm attempting to write a C# WebSocket server for an application that interacts upon browser input.

This is the code:

class Program {
 static void Main(string[] args) {
  var listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 42001);
  listener.Start();
  using(var client = listener.AcceptTcpClient())
  using(var stream = client.GetStream())
  using(var reader = new StreamReader(stream))
  using(var writer = new StreamWriter(stream)) {
   while (!reader.EndOfStream) {
    String line = reader.ReadLine();

    if (new Regex("^GET").IsMatch(line)) {
     line = reader.ReadLine();
     if (new Regex("^Sec-WebSocket-Key: ").IsMatch(line)) {
      String key = new Regex("(^Sec-WebSocket-Key\\: |\\r\\n)").Replace(line, "");

      key = Convert.ToBase64String(SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11")));

      writer.WriteLine("HTTP/1.1 101 Switching Protocols");
      writer.WriteLine("Upgrade: websocket");
      writer.WriteLine("Connection: Upgrade");
      writer.WriteLine("Sec-WebSocket-Accept: " + key);
      writer.WriteLine("Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits");
      writer.WriteLine("WebSocket-Origin: http://127.0.0.1");
      writer.WriteLine("WebSocket-Location: ws://localhost:42001/websocket");
      writer.WriteLine("");
     }
    }
   }
  }
  listener.Stop();
 }
}

... and:

        var ws = new WebSocket('ws://localhost:42001/websocket');

        ws.onopen = function() {
            console.log('connected');
        };

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

        ws.onerror = function(e) {
            console.log(e);
        };

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

On execution, the TPCListener successfully accepts the TCPClient and reads the incoming HTTP request. It parses the Key, generates the correct Accept token, but the JS - window native - WebSocket seems to have gone flat out bonkers: it does not answer no matter what it receives. I would expect it throwing an error upon sending a HTTP/1.1 400 Bad Request, but nothing at all happens. It just goes mute. Checking out Chrome Dev Tools' Networking tab, I do only see the websocket outgoing GET request, but no incoming packets - is that supposed to happen? If I forcefully close the application, WebSocket throws this exception:

WebSocket connection to 'ws://localhost:42001/websocket' failed: Error during WebSocket handshake: net::ERR_CONNECTION_RESET.

What am I missing here? Thank you all in advance.

Also, I'm not using Net.WebSockets because it is available since .NET 4.5, and my application targets systems from Windows 7 to the current build of Windows 10.

anon123
  • 43
  • 5

1 Answers1

1

well... how far does your C# code get? My first bet would be on buffering - you don't flush the writer or stream, so I would expect them to be holding onto data while stuck in the top of the while loop, but frankly it shouldn't be a while loop in the first place - you only get one handshake per socket, not many. You could try adding flushes after the blank line, and you should make sure the Socket itself has buffering disabled (NoDelay = true;) - but: fundamentally this isn't a good way to write a web-socket server. Apart from anything else, the data will cease to be text if the handshake succeeds, so having a TextReader is a very bad thing. Frankly, you should be dealing with raw Socket / byte[] data here, IMO (having implemented this very thing several times).

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Your first bet was very much correct, thank you. I did flush the writer and hands were quite successfully shook - I'm so sorry. I appreciate the tips! – anon123 Jun 13 '17 at 17:16
  • @Marc Gravell Since you have implemented WebSockets several times can you please take a look at my post and provide me with a code sample? My post https://stackoverflow.com/questions/47481999/c-sharp-websockets-on-windows-7-with-owin – GamerDev Nov 25 '17 at 12:33