why I received this:received string, when I send this?sended string
Cod of client app:
try
{
tcpclient.Connect("127.0.0.1", 80);
String str = "LOG" + Login.Text + "$" + hasło.Text;
Stream stm = tcpclient.GetStream();
ASCIIEncoding asen = new ASCIIEncoding();
byte[] buffer = asen.GetBytes(str);
stm.Write(buffer, 0, buffer.Length);
Cod of host:
try
{
string msg = "";
Socket socket = Listerner.AcceptSocket();
ASCIIEncoding asen = new ASCIIEncoding();
int x = socket.ReceiveBufferSize;
byte[] buffor = new byte[x];
int data = socket.Receive(buffor);
string wiadomość = Encoding.ASCII.GetString(buffor);
This is because your buffor variable at the host has a fixed size and thus Encoding.ASCII.GetString will try to convert the complete byte array back to a string, regardless how many bytes were actually received.
socket.Receive returns the number of bytes that were actually received. Use this information to restore the string:
int bytesReceived = socket.Receive(buffor);
string wiadomość = Encoding.ASCII.GetString(buffor, 0, bytesReceived);
See Encoding.ASCII.GetString and Socket.Receive for reference.
Now it should work for your tiny example. But be aware that you might receive more bytes than your buffer can take at once. So you have to do something like:
string messageReceived = "";
int bytesReceived = 0;
do
{
bytesReceived = socket.Receive(buffor)
messageReceived += Encoding.ASCII.GetString(buffor, 0, bytesReceived);
} while(bytesReceived >= buffor.Length)
// now messageReceived should contain the whole text
Related
So I am sending a simple string from my TCP Client to my server and then when I receive it it decodes the bytes and prints out what it got.. However I am sending
Client connecting..
and I receive
Client connecting..\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0
Why is that?
The buffer seems to be the same, 18 bytes with the empty ones being 0
is this due to the Encoding method? I've tried different ones likes Default and UTF8 but it seems to do the same still.
_listener.Start();
Console.WriteLine("Waiting for connection..");
//Assign our client the value of the first accepted request.
_client = _listener.AcceptTcpClient();
Console.WriteLine("Client connected.");
//Set the stream to listen for incoming requests.
_stream = _client.GetStream();
//Build the package
byte[] buffer = new byte[128];
var bufferLength = _stream.Read(buffer, 0, buffer.Length);
return buffer;
And it passes the byte array to this
public void SendPacket(byte[] buffer)
{
TcpClient client = new TcpClient(hostName, portNum);
NetworkStream ns = client.GetStream();
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine($"Received from remote client: {Encoding.UTF8.GetString(buffer, 0, buffer.Length)}");
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"Relaying to the remote server: {Encoding.UTF8.GetString(buffer, 0, buffer.Length)}");
ns.Write(buffer, 0, buffer.Length);
}
And then
Console.WriteLine("Data Received..");
var data = Encoding.UTF8.GetString(buffer, 0, length);
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("Received: " + data);
According to your code
var bufferLength = _stream.Read(buffer, 0, buffer.Length);
return buffer;
bufferLength is dropped on the floor.
var data = Encoding.UTF8.GetString(buffer, 0, length);
I don't know where length came from, but I suppose it's the buffer's length. Since the receive didn't fill up the whole buffer but only part of it, you must use bufferLength to know how many bytes to work with.
Same problem here:
var eh = ns.Read(newBuffer, 0, newBuffer.Length);
var received = Encoding.ASCII.GetString(newBuffer, 0, newBuffer.Length);
Use eh!
var eh = ns.Read(newBuffer, 0, newBuffer.Length);
var received = Encoding.ASCII.GetString(newBuffer, 0, eh);
\0 is the "empty" value for a char object, so most likely it is reading the chars.
I'm currently working on a TCPClient and Server. Lately I added an encryption for the messages, and had no trouble. Once I started noticing that I'm getting a weird error like this:
But It's totally random, and no idea why. It happens at larger messages, but as I said, not always.
Checking the byte[] length at the server side says 1920 (Sometimes it says 1920 on the client too, and thats the point when i dont have error)
On client it says a lot lesser.
I actually think that sometimes the client doesn't receive the full byte that It should, this is how I do It:
Client:
byte[] bb = new byte[12288];
int k = stm.Read(bb, 0, 12288);
string message = Encoding.UTF8.GetString(bb, 0, k);
MessageBox.Show(message.Length.ToString()); // This sometimes says 1460, and 1920
message = Encrypter.DecryptData(message); // Error here If the length is not 1920
Server:
bmsg = Encrypter.EncryptData(((int)Codes.XYZEnum) + "=" + data);
Logger.Log(bmsg.Length.ToString()); // Original msg, always says 1920
s.Send(asen.GetBytes(bmsg));
s.Close();
What could be the problem? Should I try async sending?
SOLUTION:
Server code, took me a little while to make it cool:
System.Net.Sockets.Socket s = myList.AcceptSocket(); // Accept the connection
Stream stream = new NetworkStream(s); // Create the stream object
byte[] leng = new byte[4]; // We will put the length of the upcoming message in a 4 length array
int k2 = s.Receive(leng); // Receive the upcoming message length
if (BitConverter.IsLittleEndian)
{
Array.Reverse(leng);
}
int upcominglength = (BitConverter.ToInt32(leng, 0)); // Convert it to int
byte[] b = ByteReader(upcominglength, stream); // Create the space for the bigger message, read all bytes until the received length!
string message = Encoding.UTF8.GetString(b, 0, b.Length); // Convert it to string!
internal byte[] ByteReader(int length, Stream stream)
{
byte[] data = new byte[length];
using (MemoryStream ms = new MemoryStream())
{
int numBytesRead;
int numBytesReadsofar = 0;
while (true)
{
numBytesRead = stream.Read(data, 0, data.Length);
numBytesReadsofar += numBytesRead;
ms.Write(data, 0, numBytesRead);
if (numBytesReadsofar == length)
{
break;
}
}
return ms.ToArray();
}
}
Client code, and it is working nicely!:
var result = tcpclnt.BeginConnect(User.IP, User.Port, null, null);
var success = result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(3)); // Connect with timeout
if (!success)
{
return "Failed to connect!";
}
Stream stm = tcpclnt.GetStream(); // get the stream
UTF8Encoding asen = new UTF8Encoding();
byte[] ba = asen.GetBytes(msg); // get the bytes of the message we are sending
byte[] intBytes = BitConverter.GetBytes(ba.Length); // Get the length of that in bytes
if (BitConverter.IsLittleEndian)
{
Array.Reverse(intBytes);
}
stm.Write(intBytes, 0, intBytes.Length); // Write the length in the stream!
stm.Flush(); // Clear the buffer!
stm.Write(ba, 0, ba.Length); // Write the message we are sending!
// If we have answers....
byte[] bb = new byte[10000];
int k = stm.Read(bb, 0, 10000);
string mmessage = Encoding.UTF8.GetString(bb, 0, k);
// If we have answers....
tcpclnt.Close(); // Close the socket
Because only 8Kb can to send by once packet. if you have large data you need use cycle.
I have a Microscan TCP/IP barcode reader. I am currently using the following code to connect to it and retrieve a barcode when read:
// responseData string will be the barcode received from reader
string responseData = null;
TcpClient client = new TcpClient("10.90.10.36", 2001);
// The "getData" is just a generic string to initiate connection
Byte[] sentData = System.Text.Encoding.ASCII.GetBytes("getData");
NetworkStream stream = client.GetStream();
stream.Write(sentData, 0, sentData.Length);
Byte[] receivedData = new Byte[20];
Int32 bytes = stream.Read(receivedData, 0, receivedData.Length);
for (int i = 0; i < bytes; i++)
{
responseData += Convert.ToChar(receivedData[i]);
}
// Closes the socket connection.
client.Close();
The issue that I am having is that I am only getting 10 characters when the barcode is 15. Everything works correctly until the Int32 bytes = stream.Read(receivedData, 0 receivedData.Length); line. The Read call is returning 10 rather than 15 as it should be. I have tried modifying the code in a few different ways, but all of them have just returned 10 characters like normal. This works correctly if the barcode is 10 characters or fewer, but not if more.
I don't think it's an issue with the scanner, but I am checking into that as well. Anyone have any ideas?
Try something like:
// responseData string will be the barcode received from reader
string responseData = null;
using (TcpClient client = new TcpClient("10.90.10.36", 2001))
{
using (NetworkStream stream = client.GetStream())
{
byte[] sentData = System.Text.Encoding.ASCII.GetBytes("getData");
stream.Write(sentData, 0, sentData.Length);
byte[] buffer = new byte[32];
int bytes;
while ((bytes = stream.Read(buffer, 0, buffer.Length)) != 0)
{
for (int i = 0; i < bytes; i++)
{
responseData += (char)buffer[i];
}
}
}
}
The while cycle will repeat itself while there are new characters that can be received. I have even put some using around your code (it's better to use them instead of Closeing manually objects)
I'm trying to send a couple of data via Sockets, so it's converted to bytes and then back to String on the Server. But I can only do one apparently.
Server code:
static void Read(IAsyncResult ar)
{
int fileNameLen = 1;
//int userNameLen = 9;
State newState = (State)ar.AsyncState; //gets state of Socket
Socket handler = newState.Socket_w; //passes Socket to handler
int bytesRead = handler.EndReceive(ar); //terminates Data Receive from Socket.
if (bytesRead > 0)
{
if (flag == 0)
{
fileNameLen = BitConverter.ToInt32(newState.buffer, 0); //gets filename length
fileName = Encoding.UTF8.GetString(newState.buffer, 4, fileNameLen); //gets filename
//userNameLen = BitConverter.ToInt32(newState.buffer, 8);
//getUsername = Encoding.UTF8.GetString(newState.buffer, 8, fileNameLen);
flag++;
}
}
}
Client code:
internal static void uploadFile(string host, string username, string getGame, string filename, string filepath)
{
byte[] m_clientData;
Socket clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
byte[] fileName = Encoding.UTF8.GetBytes(username + "_" + filename);
byte[] fileData = File.ReadAllBytes(filepath);
byte[] fileNameLen = BitConverter.GetBytes(fileName.Length);
//byte[] sendUsername = Encoding.UTF8.GetBytes(username);
//byte[] sendUsernameLen = BitConverter.GetBytes(sendUsername.Length);
//byte[] sendGame = Encoding.UTF8.GetBytes(getGame);
//byte[] sendGameLen = BitConverter.GetBytes(sendGame.Length);
m_clientData = new byte[4 + fileName.Length + fileData.Length];
fileNameLen.CopyTo(m_clientData, 0);
fileName.CopyTo(m_clientData, 4);
fileData.CopyTo(m_clientData, 4 + fileName.Length);
//sendUsernameLen.CopyTo(m_clientData, 0);
//sendUsername.CopyTo(m_clientData, 4);
//sendGameLen.CopyTo(m_clientData, 0);
//sendGame.CopyTo(m_clientData, 4);
clientSock.Connect(host, 8889);
clientSock.Send(m_clientData); //tofix exception
clientSock.Close();
}
I can't seem to decrypt it properly over on Server. Can anyone help me with the buffersizes and whatnot?
Read does not know anything about what was sent; TCP is basically just a stream - so there is absolutely nothing to say that you have all the data in one call to Read; you could have:
exactly the amount of data you sent
part of one message
17 messages
the end of one message and the start of the next
1 solitary byte from a message
You need to devise some kind of framing protocol that lets the receiver know when they have an entire message. That could be as simple as a length prefix, or can be more complex. You should then buffer the data in memory (or process it gradually) until you have the entire message. One call to Read is very unlikely to represent a single and complete message. Indeed, this is guaranteed not to be the case if a message is larger than your newstate.buffer, but you can get the same result even for small messages and a large buffer.
I have the following code:
private string Connect()
{
string responseData;
try
{
TcpClient client = new TcpClient(ServerIp, Port);
client.ReceiveBufferSize = Int32.MaxValue;
Byte[] data = Encoding.GetEncoding(1251).GetBytes(ReadyQuery);
NetworkStream stream = client.GetStream();
// send data
stream.Write(data, 0, data.Length);
// buffer
data = new Byte[65536];
Int32 bytes = stream.Read(data, 0, data.Length);
responseData = Encoding.GetEncoding(1251).GetString(data, 0, bytes);
// close all
stream.Close();
client.Close();
return responseData;
}
I have problem with a big message. The receive message size is 22K chars. I get only part of message.
How can I receive big messages?
PS. In the debugger bytes equal 4096.
You call stream.Read in a loop until you read the entire message. If you know the message size in advance it's relatively easy:
int messageSize = 22000;
int readSoFar = 0;
byte [] msg = new byte[messageSize];
while(readSoFar < messageSize)
{
var read = stream.Read(msg, readSoFar, msg.Length - readSoFar);
readSoFar += read;
if(read==0)
break; // connection was broken
}
If the message size is part of the message (say, encoded in the first 4 bytes), you should read those first and then do as I suggested.