0

About 4 hours of research...here we go.

I have a C# program that sends and listens for anything coming in a specific Socket. Using the sockets, C# can send stuff to it and can receive from it just fine. Now, going to my JavaScript file, I'm using the WebSocket interface to communicate with C#, but doesn't work (usually times out after a couple of minutes). When the Socket is online, the JavaScript code will take up to about 4 minutes then throw an error saying "WebSocket opening handshake timed out". The thing is I know that it can find because, when the port of the ip doesn't exist the JavaScript file throws an error in the next couple seconds.

Things I've done:

Turn off all firewalls, use both ws and wss at the beginning of the ip and port (ex: wss://xxx.xxx.x.xx:11111), change the port, change the ip to a valid ip still reachable, research for 4 hours.

C#:

IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddr = IPAddress.Parse("ip");
IPEndPoint localEndPoint = new IPEndPoint(ipAddr, 11111);

Socket listener = new Socket(ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

try
{
    listener.Bind(localEndPoint);

    listener.Listen(10);

    while (true)
    {

        Console.WriteLine("Waiting connection...");

        Socket clientSocket = listener.Accept();

        byte[] bytes = new Byte[1024];
        string data = null;

        while (true)
        {

            int numByte = clientSocket.Receive(bytes);

            data += Encoding.ASCII.GetString(bytes, 0, numByte);

            if (data.IndexOf("<EOF>") > -1)
            {
                break;
            }
        }

        Console.WriteLine("Text received -> {0} ", data);
        byte[] message = Encoding.ASCII.GetBytes("Test Server");

        clientSocket.Send(message);

        clientSocket.Shutdown(SocketShutdown.Both);
        clientSocket.Close();
    }
}
catch (Exception e)
{
    Console.WriteLine(e.ToString());
}

JavaScript:

socket = new WebSocket("wss://ip:11111");
socket.onopen = function()
{
    alert("Connected!");
}
socket.onerror = function()
{
    alert("Connection Failed");
}

The ip is local

Long story short, C# can communicate with itself and JavaScript can find it but can't communicate with it.

Cfun
  • 8,442
  • 4
  • 30
  • 62
JJtheJJpro
  • 81
  • 3
  • 7
  • Ok, but as I said, I have used ws. Also, I dont know how to get the `Connection: Upgrade GET ws://websocket.example.com/ HTTP/1.1 Origin: http://example.comConnection: Upgrade Connection: Upgrade Host: websocket.example.comConnection: Upgrade Upgrade: websocket` – JJtheJJpro May 18 '20 at 00:36
  • I’ve no doubt that WS has been used with a server that *correctly implements* handshaking/accepting an incoming WS request. The code above does not - as it fails to adhere to the defined protocol - and is not expected to work. – user2864740 May 18 '20 at 00:46
  • I highly suggest using `System.Net.HttpListener` which can set up a `System.Net.Websocket` connection for you via the `HttpListenerContext` / `HttpListenerRequest `. – Powerlord May 18 '20 at 00:47
  • Ok. I'll work on that right now. I'll get back as soon as I figure it out or otherwise. – JJtheJJpro May 18 '20 at 00:52
  • In fact, [this answer](https://stackoverflow.com/a/35896157/15880) tells you how to use `HttpListener` to set things up. – Powerlord May 18 '20 at 00:52

1 Answers1

1

Properly complete a handshake. (Or use a library / connection type that does.)

The WebSocket protocol (as original defined in RFC6455 - The WebSocket Protocol) does not open a plain unrestricted socket, in part for security reasons.

Since the handshake is not complete, the client WS request will timeout as the HTTP “Upgrade” response is never received. Until the handshake is complete, the WS will not be active over the underlying TCP connection.

Initiating a WebSocket connection (“the handshake”) is defined in section 4 of the RFC. It is also discussed in How JavaScript works: Deep dive into WebSockets and HTTP/2 with SSE + how to pick the right path.

The client establishes a WebSocket connection through a process known as the WebSocket handshake. This process starts with the client sending a regular HTTP request to the server. An Upgrade header is included in this request which informs the server that the client wishes to establish a WebSocket connection.

..

Now that [after] the handshake is complete the initial HTTP connection is replaced by a WebSocket connection that uses the same underlying TCP/IP connection. At this point, either party can start sending data.

Community
  • 1
  • 1
user2864740
  • 60,010
  • 15
  • 145
  • 220
  • I have no idea where the `GET ws://websocket.example.com/ HTTP/1.1 Origin: http://example.com Connection: Upgrade Host: websocket.example.com Upgrade: websocket` goes. And do I properly complete the handshake in C# or JavaScript? – JJtheJJpro May 18 '20 at 00:44
  • The JS side is correct, as implemented by the browser and the WebSocket type (which properly sends the initial handshake and waits for the connection to be upgraded). The C# side is incorrect as it never completes the required handshake. – user2864740 May 18 '20 at 00:48
  • Either write a (minimally) valid implementation (see the RFC, etc. https://tools.ietf.org/html/rfc6455) or use an existing valid library that understands how to accept a WS handshake/connection. A minimally valid implementation might simply return the required HTTP and “Upgrade” headers. – user2864740 May 18 '20 at 00:51
  • Specifically, Section 4.2 of RFC6455 - https://tools.ietf.org/html/rfc6455#section-4.2 – user2864740 May 18 '20 at 00:56
  • Looks like the HttpListener worked. Thank you so freaking much. – JJtheJJpro May 18 '20 at 01:11