Can't get the text correctly over TCP - c#

I know my title is not good but I did not know how to write this problem. I'm receiving a XML over tcp connection but the problem is the string is full of "\0" so I can't see the message when I use that string variable. I can do string.length and see It's filled but can't reach the text. I've tried replace method and it worked but I know this is not the correct solution. So here is my question how can I receive the text correctly?
TcpListener tcpListener = new TcpListener(Convert.ToInt16(_Port));
tcpListener.Start();
while (true)
{
Socket handlerSocket = tcpListener.AcceptSocket();
if (handlerSocket.Connected)
{
Control.CheckForIllegalCrossThreadCalls = false;
NetworkStream networkStream = new NetworkStream(handlerSocket);
byte[] myReadBuffer = new byte[102400000];
int numberOfBytesRead = 0;
string myCompleteMessage = "";
do
{
numberOfBytesRead = networkStream.Read(myReadBuffer, 0, myReadBuffer.Length);
myCompleteMessage += Encoding.UTF8.GetString(myReadBuffer,
}
while (networkStream.DataAvailable);
Console.WriteLine("Text: "+myCompleteMessage);
}
}
I've tried to change the Encoding.UTF8 to Encoding.ASCII and Encoding.UNICODE but it did not worked.
Update: My problem is still continue, the data I receive has "\0" before every character. I couldn't find why.. I use replace and inserting \0 again once I want to send data back. Can this be because of some sort of encoding? I've tried getEncodings aswell and tried many code pages but non work

It turns all the "\0"'s inside my string was because the data I receive was encoded with BigEndian.. when I used
myCompleteMessage += Encoding.BigEndianUnicode.GetString(myReadBuffer, 0, numberOfBytesRead);
everything worked well. Wanted to share this here in case if someone receive the same problem.

Related

Connecting to Serial->Ethernet converter box via Telnet, getting strange response (no matter what I send)

I'm trying to communicate with a device that has a Serial COM port that goes out (using RS232 Protocol), which I've hooked up to a converter box that converts the connection to Ethernet.
I've successfully connected to the converter box (which has its own IP) and I've successfully communicated with the device by sending it commands over telnet by using PuTTY, to which it has responded with various data that I've been able to parse.
I've established a connection by creating a new TcpClient, and I'm able to send strings to the device, but every time I get a response back, it's always "??\u0003" which I've researched and found that \uhhhh is a Unicode escape protocol. This confuses me because I have used ASCII encoding for everything.
public string TcpConnect(string cmd)
{
var client = new TcpClient();
//cmd = "ping";
Console.WriteLine("Connecting to server");
client.Connect("169.254.20.40", 23); //22 = ssh, 23 = telnet, 80 = http
Console.WriteLine("CONNECTED SUCCESSFULLY");
Stream tcpStream = client.GetStream();
ASCIIEncoding A = new ASCIIEncoding();
byte[] enable = A.GetBytes("enable" + Environment.NewLine);
byte[] connect = A.GetBytes("connect line 1" + Environment.NewLine);
byte[] ba = A.GetBytes(cmd);
Console.WriteLine("Transmitting.....");
tcpStream.Write(enable, 0, enable.Length);
tcpStream.Write(connect, 0, connect.Length);
tcpStream.Write(ba, 0, ba.Length);
byte[] responseBytes = new byte[4096];
int numBytesRead = tcpStream.Read(responseBytes, 0, responseBytes.Length);
var message = A.GetString(responseBytes, 0, numBytesRead);
Console.WriteLine("\nServer Closed.");
return message;
}
If I were to pass in "$TEAA4B9\r\n" as the message, I would expect something along the lines of "$TEA,086,040,031,000,3798" which is nowhere close to what I'm getting (which is ??\u0003)
Nevermind figured it out
Just kidding! Here's what I did: I added a "System.Threading.Thread.Sleep("1000") before the "tcpStream.Read" line at the bottom, and now it outputs the data I need. The device was outputting garbage on the first line (perhaps a handshake, not sure) and that's all that was being read before it was being stored into "message" and returned (not enough time was spent reading before it moved on to the next line of code)

Using TcpClient on websocket receive data get \0\0\0\0

I have establish a connection with a websocket , i want to receive message from it. Following is my code for receiving message from the websocket.
//mClient is my TCP connection
byte[] bytes;
NetworkStream netStream;
string returndata;
while(true)
{
bytes = new byte[mClient.ReceiveBufferSize];
netStream = mClient.GetStream();
netStream.Read(bytes, 0, (int)mClient.ReceiveBufferSize);
returndata = Encoding.UTF8.GetString(bytes);
Console.WriteLine("This is what the host returned to you: " + returndata);
}
The data should be some json array when I open with browser , but i have receive weird data like
??\0\0\0\0\0\0\0\0\0\0\
And the second loop onwards is forever
\0\0\0\0\0\0\0\0\0\0\0
I have seen a Similar Question but i have no idea on his answer. May I know how to fix this thing and what is the problem ?
Just read the stream with a StreamReader instead of fiddling with array buffers and the encoding by yourself:
//mClient is my TCP connection
StringBuilder returndata = new StringBuilder();
Console.Write("This is what the host returned to you: ");
// the StreamReader handles the encoding for you
using(var sr = new StreamReader(mClient.GetStream(), Encoding.UTF8))
{
int value = sr.Read(); // read an int
while(value != -1) // -1 means, we're done
{
var ch = (char) value; // cast the int to a char
Console.Write(ch); // print it
returndata.Append(ch); // keep it
value = sr.Read(); // read next char
}
}
Console.WriteLine(" done.");
capture the result in a StringBuilder so you can convert that to a string if the loop ends (based on whatever condition that will be)
It won't work like that. WebSockets uses a framing protocol that you have to parse. Your JSON payload will be wrapped in one or multiple frames you need to read and parse.
https://www.rfc-editor.org/rfc/rfc6455#section-5.2

Why removig TextBox.AppendText() from my code changes socket communication here?

I have a simple client/server communication between C++ and C# where the C# program sends a string to the C++.
Sending of a string is done on 3 stages. Send the length of the length of the string--> Send the length of string --> Send the String.
For debugging purposes I have a TextBox called textbox1 on my C# program to print
the sent values using textbox1.AppendText() three times for the three values sent.
Everything was sent and received correctly, When I remove two of the three AppendText() lines from my code it still works but the strange thing is when I remove the third one (Commented as //<--This Line, The C++ server receives 0!
C# Client (Code Snippet):
private void button1_Click(object sender, EventArgs e)
{
try
{
MemoryStream ms;
NetworkStream ns;
TcpClient client;
BinaryWriter br;
byte[] tosend;
string AndroidId = "2468101214161820";
string len = AndroidId.Length.ToString();
string lol = len.Length.ToString();
ms = new MemoryStream();
client = new TcpClient("127.0.0.1", 8888);
ns = client.GetStream();
br = new BinaryWriter(ns);
//****************Send Length Of Length***************
tosend = System.Text.Encoding.ASCII.GetBytes(lol);
br.Write(tosend);
textBox1.AppendText(Encoding.ASCII.GetString(tosend));//<---THIS LINE
//****************Send Length***************
tosend = System.Text.Encoding.ASCII.GetBytes(len);
br.Write(tosend);
//****************Send Length Of Length***************
tosend = System.Text.Encoding.ASCII.GetBytes(AndroidId);
br.Write(tosend);
ns.Close();
client.Close();
}
C++ Server Code Snippet:
//***********Recieve Length Of Length*****************
char* lol_buff0 = new char[1];
int nullpoint= recv(s, lol_buff0, strlen(lol_buff0), 0);
lol_buff0[nullpoint] = '\0';
int lengthoflength = atoi(lol_buff0);
//***********Recieve Length*****************
char* l_buff0 = new char[lengthoflength];
int nullpoint2=recv(s, l_buff0, strlen(l_buff0), 0);
l_buff0[nullpoint2] = '\0';
int length = atoi(l_buff0);
//***********Recieve AndroidID*****************
char* AndroidID = new char[length];
valread0 = recv(s, AndroidID, strlen(AndroidID), 0);
if (valread0 == SOCKET_ERROR)
{
int error_code = WSAGetLastError();
if (error_code == WSAECONNRESET)
{
//Somebody disconnected , get his details and print
printf("Host disconnected unexpectedly , ip %s , port %d \n", inet_ntoa(address.sin_addr), ntohs(address.sin_port));
//Close the socket and mark as 0 in list for reuse
closesocket(s);
client_socket[i] = 0;
}
else
{
printf("recv failed with error code : %d", error_code);
}
}
if (valread0 == 0)
{
//Somebody disconnected , get his details and print
printf("Host disconnected , ip %s , port %d \n", inet_ntoa(address.sin_addr), ntohs(address.sin_port));
//Close the socket and mark as 0 in list for reuse
closesocket(s);
client_socket[i] = 0;
}
else
{
//add null character, if you want to use with printf/puts or other string handling functions
AndroidID[valread0] = '\0';
printf("%s:%d Your Android ID is - %s \n", inet_ntoa(address.sin_addr), ntohs(address.sin_port), AndroidID);
}
I know I can accommodate the TextBox as long as it works but It is so weird and I'd like to know what is the explanation for that. Thanks.
You're assuming that the data will be received in one recv call (or alternatively, that one send corresponds to one receive). That is a false assumption. You need to keep reading until you read length of bytes of data. TCP doesn't have any messaging built in, it only deals with streams.
Adding the line may mean that some small delay is added which makes the receive happen in a single call - it's hard to tell, since you're dealing with something that isn't quite deterministic. Handle TCP properly, and see if the problem persists.

C# Socket Receive to String

Following this guide I wrote the following function:
public string ConnectToHost(string ip, int port)
{
Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
IPAddress host = IPAddress.Parse(ip);
IPEndPoint ipep = new IPEndPoint(host, port);
socket.Connect(ipep);
byte[] msg = Encoding.Unicode.GetBytes("<Client Quit>");
int msgSend = socket.Send(msg);
byte[] bytes;
int byteRecieve;
String msgRecieved = Encoding.Unicode.GetString(bytes, 0, byteRecieve);
while (socket.Available > 0)
{
byteRecieve = socket.Receive(bytes);
msgRecieved += Encoding.Unicode.GetString(bytes, 0, byteRecieve);
}
socket.Shutdown(SocketShutdown.Both);
socket.Close();
return msgRecieved;
}
But I get error
Use of unassigned local variable 'bytes' and Use of unassigned local variable 'byteRecieve'
on the lie of code
String msgRecieved = Encoding.Unicode.GetString(bytes, 0, byteRecieve);
Removing the Encoding.Unicode.GetString(bytes, 0, byteRecieve); from the line and only have String msgRecieved; gave the same error but within the while loop.
How do I get this function to return the recieved bytes as string?
Well, it's true that you are using those variables without them being assigned, no? That's not allowed because it's unclear what that means. In this case you can make it work by saying:
byte[] bytes = new byte[4096];
int byteRecieve = 0;
When you have solved those compiler errors, which have nothing to do with sockets, you'll find that using Available underestimates the amount of data that's incoming. It is almost never useful.
Also, you'll find that Unicode encoded strings cannot be broken up at arbitrary boundaries so this does not work either. Use StreamReader.
You probably should keep looking for a different tutorial. Most are very broken. TCP is very hard to get right.
Look at these two lines of code:
int byteRecieve;
and
String msgRecieved = Encoding.Unicode.GetString(bytes, 0, byteRecieve);
In the first line you declare byteRecieve, but do not assign a value to it. In the second line you make use of it. Since you have not assigned a value to it you get the error message.
Since you do the right thing inside the while loop, you can simply delete the second line above....
Also
byte [] bytes;
should become something like
byte [] bytes = new bytes[256];
or similar. Again your version merely declared bytes to be an array of byte, but did not allocate/assign that an actual array value to it.

Send server multiple messages? C#

I have a quick and dirty question. So as it stands, i have two clients and a server running. I can communicate messages from the clients to the server without any problem. my problem appears when i want to read two messages from the client - rather than just one message.
The error which i receive is: IOException was unhandled. Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
Here is my code on the server side:
private static void HandleClientComm(object client)
{
/** creating a list which contains DatabaseFile objects **/
List theDatabase = new List();
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] message = new byte[4096];
int bytesRead;
do
{
bytesRead = 0;
try
{
// Blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 4096);
}
catch (Exception)
{
// A socket error has occured
break;
}
if (bytesRead == 0)
{
// The client has disconnected from the server
break;
}
// Message has successfully been received
ASCIIEncoding encoder = new ASCIIEncoding();
Console.WriteLine("To: " + tcpClient.Client.LocalEndPoint);
Console.WriteLine("From: " + tcpClient.Client.RemoteEndPoint);
Console.WriteLine(encoder.GetString(message, 0, bytesRead));
if (encoder.GetString(message, 0, bytesRead) == "OptionOneInsert")
{
byte[] message2 = new byte[4096];
int bytesRead2 = 0;
**bytesRead2 = clientStream.Read(message, 0, 4096);** //ERROR occurs here!
Console.WriteLine("Attempting to go inside insert)");
Menu.Insert(theDatabase, bytesRead2);
}
Here is my client code:
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("OptionOneInsert");
Console.ReadLine();
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
NetworkStream clientStream2 = client.GetStream();
String text = System.IO.File.ReadAllText("FirstNames.txt");
clientStream2.Write(buffer, 0, buffer.Length);
clientStream2.Flush();
ASCIIEncoding encoder2 = new ASCIIEncoding();
byte[] buffer2 = encoder2.GetBytes(text);
Console.WriteLine("buffer is filled with content");
Console.ReadLine();
When the client sends the message "optionOne" it is received by the server just fine. It's only when i attempt to send the string called "text" that the issues appears!
Any help would be greatly appreciated - I'm not all that familiar with Sockets, hence i've been struggling with trying to understand this for sometime now
You've got a big problem here - there's nothing to specify the end of one message and the start of another. It's quite possible that the server will receive two messages in one go, or half a message and then the other half.
The simplest way of avoiding that is to prefix each message with the number of bytes in it, e.g. as a fixed four-byte format. So to send a message you would:
Encoding it from a string to bytes (ideally using UTF-8 instead of ASCII unless you're sure you'll never need any non-ASCII text)
Write out the length of the byte array as a four-byte value
Write out the content
On the server:
Read four bytes (looping if necessary - there's no guarantee you'd even read those four bytes together, although you almost certainly will)
Convert the four bytes into an integer
Allocate a byte array of that size
Loop round, reading from "the current position" to the end of the buffer until you've filled the buffer
Convert the buffer into a string
Another alternative is simply to use BinaryReader and BinaryWriter - the ReadString and WriteString use length-prefixing, admittedly in a slightly different form.
Another alternative you could use is to have a delimiter (e.g. carriage-return) but that means you'll need to add escaping in if you ever need to include the delimiter in the text to transmit.

Categories