C# WebSocketClient always receives garbage data - c#

I am connecting to a websocket server in C# using WebSocketClient class. I can connect to it successfully as the socket state changes to Open. When I try to receive data from the socket I get garbage data always.
the garbage data looks like following
\u0002\u0004\0\u0003Y\\0\04D\0\0\0\0^��$\0\0\0\0����
The client side code works fine if I connect to other server. Server is a third party.
var buffer = new ArraySegment<byte>(new byte[8192]);
using (var ms = new MemoryStream())
{
WebSocketReceiveResult result;
do
{
ct.ThrowIfCancellationRequested();
result = await socket.ReceiveAsync(buffer, ct);
ms.Write(buffer.Array), buffer.Offset, result.Count);
}
while (!result.EndOfMessage);
ms.Seek(0, SeekOrigin.Begin);
if (result.MessageType == WebSocketMessageType.Binary)
{
using (var reader = new StreamReader(ms, Encoding.UTF8))
{
//garbage data in str
var str = await reader.ReadToEndAsync();
return feed;
}
}
Any idea why this happens?
Third party server is http://antplus.aliceblueonline.com/#feeds-api

Related

How to read and write data in tcp socket client/server

I was trying to accept some data from client, send it to the server and also send feedback from server to the client again. When server only gets some data, everething works fine. While trying to implement two-way communication, server just hungs.
Server's code:
var tcpListener = new TcpListener(IPAddress.Any, 8888);
try
{
tcpListener.Start();
Console.WriteLine("Server is currently run, waiting for incoming connections");
while (true)
{
using var tcpClient = await tcpListener.AcceptTcpClientAsync();
await using var stream = tcpClient.GetStream();
var incomeData = await DeserializeHelper.ConverteToBytes(stream);
var incomePerson = MessagePackSerializer.Deserialize<Person>(incomeData);
Console.WriteLine($"Income message from {incomePerson.Name}: '{incomePerson.Message}'");
var responseMessage = $"Thank you, {incomePerson.Name} for the message";
var responceData = MessagePackSerializer.Serialize(responseMessage);
await stream.WriteAsync(responceData);
}
}
finally
{
tcpListener.Stop();
}
Client's code:
using TcpClient tcpClient = new TcpClient();
await tcpClient.ConnectAsync("127.1.199.250",8888);
Console.WriteLine("Hello, client!");
try
{
var stream = tcpClient.GetStream();
Console.WriteLine("Enter your name");
var name = Console.ReadLine();
Console.WriteLine("Enter message");
var message = Console.ReadLine();
Person tom = new Person(name, message);
var sentData = MessagePackSerializer.Serialize(tom);
await stream.WriteAsync(sentData);
Console.WriteLine("Message was sent to the server");
var incomeResponce = await DeserializeHelper.ConverteToBytes(stream);
var incomeResponceMessage = MessagePackSerializer.Deserialize<string>(incomeResponce);
Console.WriteLine($"Server's message: {incomeResponce}");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
Also all of them using my own static method ConverteToBytes, here it's code:
public static async Task<byte[]> ConverteToBytes(NetworkStream stream)
{
await using var ms = new MemoryStream();
byte[] bytesData = null;
int count = 0;
do
{
byte[] buffer = new byte[1024];
count = await stream.ReadAsync(buffer,0,1024);
ms.Write(buffer,0,count);
} while (stream.CanRead && count > 0);
return bytesData = ms.ToArray();
}
I guess the problem is with not correct stream using, but don't know what exactly is wrong. Thank's everyone!
I strongly recommend not using TCP/IP in the first place. If possible, use a well-established protocol with good library support, e.g., HTTP or WebSockets. Writing a correct TCP/IP application is extremely difficult.
If you must use TCP/IP, then I recommend watching my video series on the subject and reading my TCP/IP .NET Sockets FAQ.
Of particular note is that network streams are streams of bytes, not streams of messages. So there's no built-in way to know when a message completes. So you'll have to add that to your protocol yourself, i.e., using message framing. I describe message framing on my blog, and the video series linked above shows a more modern way to do it.
Without message framing, your server is likely just waiting for more bytes to arrive from the client connection.

Receiving messages using ClientWebSocket Class throws exception: The WebSocket received a frame with one or more reserved bits set

I 'd like to make a websocket client to connect to a third-party web socket server.
I am using ClientWebSocket Class:
public WSClientService(ClientWebSocket client, ILogger<WSClientService> logger)
{
_client = client;
_logger = logger;
}
For receiving messages i use this method:
public async Task GetMessagesAsync()
{
while (_client.State == WebSocketState.Open)
{
var chunkSize = 1024 * 4;
var buffer = new ArraySegment<byte>(new byte[chunkSize]);
do
{
WebSocketReceiveResult result;
using var ms = new MemoryStream();
try
{
do
{
//here throws exception
result = await _client.ReceiveAsync(buffer, CancellationToken.None);
ms.Write(buffer.Array, buffer.Offset, result.Count);
} while (!result.EndOfMessage);
if (result.MessageType == WebSocketMessageType.Close)
{
break;
}
ms.Seek(0, SeekOrigin.Begin);
using var reader = new StreamReader(ms, Encoding.UTF8);
var message = await reader.ReadToEndAsync();
_logger.LogInformation(message);
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
} while (_client.State != WebSocketState.Aborted);
}
}
But for some messages i get this exception message :
The WebSocket received a frame with one or more reserved bits set
I noticed that this occurs probably by some compression because i can receive small messages. The exception thrown when calling this result = await _client.ReceiveAsync(buffer, CancellationToken.None);
Does anybody knows how to solve this problem?
The solution came with .net 6 release. Well the problem occured because there was no way to add compression in built-in ClientWebSocket in .net 5 and back (Except if someone would create an extension method for compression). Now with .net 6 there is a new option named DangerousDeflateOptions. This adds the corresponding header as well.
_ws.Options.DangerousDeflateOptions = new WebSocketDeflateOptions
{
ServerContextTakeover = false,
ClientMaxWindowBits = 15 // this is the default value
};
await _ws.ConnectAsync(new Uri(_url), token).ConfigureAwait(false);

WriteLineAsync or ReadAsync unable to read string for TCP Communicator C#

I am creating a TCP Server/Client to communicate with each other using multithread and I'm having trouble getting the Server to correctly read strings that my Client is sending. For example, I send the string "testing" from the Client to the Server. On the server console, it instead reads "Received System.Net.Sockets.NetworkStream". I've been stuck on it for a couple hours and I am at a loss at how to approach this situation. Any help with be greatly appreciated.
TLDR: Server and client can communicate with each other but server can't correctly read string sent from client.
Server Code:
async Task EchoAsync(TcpClient client, CancellationToken ct)
{
var buf = new byte[4096];
var stream = client.GetStream();
while (!ct.IsCancellationRequested)
{
var amountRead = await stream.ReadAsync(buf, 0, buf.Length, ct);
WriteToConsole("Received " + stream.ToString(), 0);
if (amountRead == 0)
{
break; // End of stream
}
await stream.WriteAsync(buf, 0, amountRead, ct);
}
}
Client Code:
private async void ClientToServerMsg_btn_Click(object sender, RoutedEventArgs e)
{
using (var NetworkStream = clientSocket.GetStream())
using (var writer = new StreamWriter(NetworkStream))
{
//writer.AutoFlush = true;
WriteToConsole("Writing to server...", 1);
await writer.WriteLineAsync(ClientToServerMsg.Text);
}
}
Try
WriteToConsole("Received " + System.Text.Encoding.ASCII.GetString(buf), 0);
Instead
WriteToConsole("Received " + stream.ToString(), 0);

UdpClient stops sending messages after second client joins

I have some code for a server and client, with the server potentially having multiple clients. When it is one client and one server, I am sending and receiving messages perfectly. However, when a second user joins, the clients no longer receive the messages.
Here's how I'm sending the messages serverside:
if (Clients.Count == 0)
return;
foreach (ConnectedClient client in Clients)
{
BinaryFormatter messageFormatter = new BinaryFormatter();
try
{
using (var ms = new MemoryStream())
{
messageFormatter.Serialize(ms, new Message() { Content = new GameData(Clients), MessageType = EServerCommand.GameUpdate, origin = (IPEndPoint)Client.Client.LocalEndPoint });
Client.Send(ms.ToArray(), ms.ToArray().Length, new IPEndPoint(client.ConnectionPlayer.ClientIP, 42070));
}
}
catch (Exception e)
{
return;
}
}
Clientside, I am receiving the messages like so:
public async void HandleServerMessages()
{
while(true)
{
var message = await Receive();
if (message.MessageType == EServerCommand.GameUpdate)
{
GameUpdateEvent((GameData)message.Content);
}
}
}
public override async Task<Message> Receive()
{
var result = await Client.ReceiveAsync();
using (var memStream = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
memStream.Write(result.Buffer, 0, result.Buffer.Length);
memStream.Seek(0, SeekOrigin.Begin);
var message = formatter.Deserialize(memStream);
return (Message)message;
}
}
Like I mentioned earlier, a single client and server works as expected, the problems only arise when a second client connects.
EDIT: I have since tried using wireshark, it seems the client computer is receiving the packets, but the client code is not registering this as a "receive". Here's what wireshark is showing (10.0.0.157 is the computer, 10.0.0.170 is the server.

Two way communication using TCP Client only

When dealing with TCP Client, especially when the stream has to be encrypted, the message will not be passed unless the CryptoCtream is closed and this results in the inner stream to be not readable as it will be disposed.
For instance
TCPClient client = new TCPClient("some ip", 1234);
using(var i = new CryptoStream(client.GetStream(), myEncryptor(), CryptoStreamMode.Write) {
i.Write(some Data, 0, 1024);
}
I've tried the flush but it seems that the data can be communicated only FROM the client to server this way. Being aware of all the alternatives, I'm curious about how this could be made possible (sending data using TCP Client and receiving a response even without setting a second channel).
use an intermediate MemoryStream
var memstr = new MemoryStream();
using (var i = new CryptoStream(memstr.....)
{
i.Write(some data);
var buf = memstr.GetBuffer();
client.GetStream().Write(buf);
}
var inp = client.GetStream.Read(..);
var memstr2 = new MemoryStream(inp);
using (var o = new CryptoStream(memstr2,...))
{
var x = memstr2.Read();
}

Categories