[Edit] Please jump to the bottom for the latest edits...
I am developing a console application using a TcpListener
to receive requests from clients:
mWebSocketServer = new TcpListener(ipWebSocketAddr, mcintWebSocketPort);
ipWebSocketAddr
contains 192.168.5.73
, mcintWebSocketPort
contains 443
. I start listening and create a thread to manage clients and received data:
try {
mWebSocketServer.Start();
mWebSocketThread = new Thread(() => webSocketServer());
mWebSocketThread.Start();
} catch (Exception ex) {
FrmMain.UpdateTaskbar(ex.ToString());
}
The thread:
public async void webSocketServer() {
Byte[] arybytData = new byte[1024];
while (mblnRunTillStopped == true) {
try {
TcpClient tcpClient = mWebSocketServer.AcceptTcpClient();
Console.WriteLine(FrmMain.strTimeStampMsg("webSocket client connected"));
NetworkStream stream = tcpClient.GetStream();
int i;
while ((i = stream.Read(arybytData, 0, arybytData.Length)) != 0) {
string strRX = System.Text.Encoding.ASCII.GetString(arybytData, 0, i);
Console.WriteLine(FrmMain.strTimeStampMsg("From web-client: " + strRX));
string strTX = "Acknowledge";
byte[] arybytTX = System.Text.Encoding.ASCII.GetBytes(strTX);
stream.Write(arybytTX, 0, arybytTX.Length);
}
Thread.Sleep(mcintWebSocketServerThreadSleep);
} catch (Exception ex) {
FrmMain.UpdateTaskbar(ex.Message);
}
}
}
A client would send data with:
webSocket.send(cstrSendMsg);
cstrSendMsg
contains msg=US
. In the C# application I report all received data to the console, what I see is:
GET / HTTP/1.1
Host: 192.168.5.73:443
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Upgrade: websocket
Origin: http://192.168.5.73
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Sec-WebSocket-Key: rlhgDPkLxwNFeA6pMZtNwg==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
I don't see anything that resembles the data, where do I look for that?
I'm using Chrome (Version 131.0.6778.86 (Official Build) (64-bit)) for the client and to debug.
This is the client-side script:
webSocket = new WebSocket(cstrServerSocketIP);
webSocket.onclose = (event) => {
DebugMsg("webSocket.onclose");
};
webSocket.onerror = (event) => {
DebugMsg("webSocket.onerror");
if (typeof event == "object" && typeof event.data != "undefined") {
DebugMsg(event.data);
}
};
webSocket.onmessage = (event) => {
DebugMsg("webSocket.onmessage: " + event.data);
};
webSocket.onopen = (event) => {
DebugMsg("webSocket.onopen: " + event.data);
};
cstrServerSocketIP
contains ws://192.168.5.73:443/
, after single stepping through this I can see in the Chrome debugger:
WebSocket connection to 'ws://192.168.5.73:443/' failed:
I have no idea why because no reason is given. This is a sample from the server side of a client interaction:
Received:
21-11-2024 14:46:03.937> From web-client:
GET / HTTP/1.1
Host: 192.168.5.73:443
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Upgrade: websocket
Origin: http://192.168.5.73
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Sec-WebSocket-Key: iURnr6DRWqF2wbtypFsLig==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Response:
HTTP/1.1 1-1 Switching Protocols
Connection: Update
Upgrade: websocket
Sec-WebSocket-Accept: AFRdDliX+pqKnGCr652yekplUAI=
Is there something wrong with the Sec-WebSocket-Accept
value?
This is what I do:
Sec-WebSocket-Key
Sec-WebSocket-Key
concatenated with "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
Sec-WebSocket-Accept
.[Edit2] I've modified the original thread so the same thread should work for both HTTP and Websockets, the modification, which is a work in progress, but it seems to have broken the web-server:
public async void httpServer() {
while (mblnRunTillStopped == true) {
try {
HttpListenerContext ctx = await mListener.GetContextAsync();
HttpListenerRequest req = ctx.Request;
if (req.IsWebSocketRequest) {
HttpListenerWebSocketContext ctxWS = await ctx.AcceptWebSocketAsync(null);
Console.WriteLine("HERE");
}
It doesn't get to the Console.WriteLine("HERE");
I still see in the client debugger:
WebSocket connection to 'ws://192.168.5.73:443/' failed:
[Another Edit] Can someone verify if I have prepared response header correctly?
He is a sample request:
GET / HTTP/1.1
Host: 192.168.5.73:443
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Upgrade: websocket
Origin: http://192.168.5.73
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Sec-WebSocket-Key: GysunwWXiQEX05sMpW7Y1g==
I then take the value GysunwWXiQEX05sMpW7Y1g==
and append 258EAFA5-E914-47DA-95CA-C5AB0DC85B11
string strKey = strWebSocketKey + mcstrWebSocketMagicString;
Then I create a SHA1 key:
byte[] arybytSHA1 = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(strKey));
And finally base64 encode:
strWebSocketAccept = Convert.ToBase64String(arybytSHA1);
The response:
HTTP/1.1 1-1 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: PuuJ05IxiUQuB9aBpBZCIBKCU38=
Something is clearly wrong because the client shows:
file.js:33 WebSocket connection to 'ws://192.168.5.73:443/' failed
I found this post: generate "Sec-WebSocket-Accept" from "Sec-WebSocket-Key"
And have used the answer to compare and verify mine is correct, but still the client reports Failed
?
As it turns out its the simplest of mistakes that cause the problems, In my original post I pasted in the problem:
HTTP/1.1 1-1 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: PuuJ05IxiUQuB9aBpBZCIBKCU38=
The above response was built on something I found online, the actual problem and error is on the very first line:
1-1
It should and must be:
101
Interestingly and amazingly, my son suggested I try using https://claude.ai, which I did, I opened it up and pasted in the HTTP request headers, then posted under it, "What's wrong with the above?", instantly it came back with the correction.