Reputation: 213
I successfully made a WebSocket server in C# which I can connect to. I make the handshake as RFC 6455 requires it.
Whatever I send (via WebSocket.send()
) to it (for example "asd") the stream only has 9 bytes of data which is "unrepresentable" by UTF8.
using System.Net.Sockets;
using System.Net;
using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
class Server
{
public static void Main()
{
TcpListener server = new TcpListener(IPAddress.Parse("127.0.0.1"), 80);
server.Start();
TcpClient client = server.AcceptTcpClient();
NetworkStream stream = client.GetStream();
Boolean isHandshaked = false;
while (true)
{
while (!stream.DataAvailable)
{
}
Byte[] bytes = new Byte[client.Available];
stream.Read(bytes, 0, bytes.Length);
if (!isHandshaked)
{
Byte[] response = Encoding.UTF8.GetBytes("HTTP/1.1 101 Switching Protocols" + Environment.NewLine
+ "Connection: Upgrade" + Environment.NewLine
+ "Upgrade: websocket" + Environment.NewLine
+ "Sec-WebSocket-Accept: " + Convert.ToBase64String(
SHA1.Create().ComputeHash(
Encoding.UTF8.GetBytes(
new Regex("Sec-WebSocket-Key: (.*)").Match(
Encoding.UTF8.GetString(bytes)
).Groups[1].Value.Trim() + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
)
)
) + Environment.NewLine
+ Environment.NewLine);
stream.Write(response, 0, response.Length);
isHandshaked = true;
}
else
{
Console.WriteLine(Encoding.UTF8.GetString(bytes));
}
}
}
}
Where I missed something?
Upvotes: 0
Views: 724
Reputation: 42205
Messages between client and server are not sent as plain text. See the data framing section of the standard for how to encode/decode them.
For your example of a client sending a 3 byte string, this will result in a message of
You can unmask a message using code like the following
byte mask[4];
byte[] msg_data;
// read message, initialising mask, msg_data
for (int i=0; i<msg_data.Length; i++)
{
msg_data[i] = msg_data[i] ^ mask[i%4]
}
If you need more detail, this previous post explains message sending/receiving and includes some helpful pseudo code.
Upvotes: 2
Reputation: 6612
You can try code below and see if it works, i suspect you are not reading full response.
byte[] buffer = new byte[4155];
int bytesRead = 0;
using (var input = client.GetStream())
{
while (true)
{
bytesRead = input.Read(buffer, 0, buffer.Length);
totalBytes += bytesRead;
if (bytesRead > 0)
// keep processing ur data here, add it to another buffer maybe
else
break; // come out of while loop if there is no data
}
}
}
Upvotes: 0
Reputation: 18460
Having an empty loop to check for data i.e. while (!stream.DataAvailable){}
is really a bad practice that you can avoid.
The read method is a blocking method
, so it will wait until the data is available
int bufferSize = 1024; // change it as you want
byte[] message = new byte[bufferSize];
readLength = stream.Read(message, 0, bufferSize);
Upvotes: 0