sslStream.Read problem: all bytes read are 0 - c#

TcpClient client = new TcpClient("69.147.112.160", 443);
SslStream sslStream = new SslStream(client.GetStream(),false,
ValidateServerCertificate,null);
try
{
sslStream.AuthenticateAsClient("mail.yahoo.com");
}
catch (AuthenticationException e)
{
return;
}
byte[] messsage = Encoding.UTF8.GetBytes(".<EOF>");
sslStream.Write(messsage);
sslStream.Flush();
byte[] buffer = new byte[4096];
int bytes2 = -1;
do
{
/**************************************************
*** JUST A LINE BELOW ALL buffer BYTES ARE ZERO!**
*************************************************/
bytes2 = sslStream.Read(buffer, 0, 4096);
m_sockClient.Send(buffer, bytes2, 0);
} while (bytes != 0);

All bytes in buffer that have not been filled in by the Read call will be zero; this is standard C#.
If every last one byte in there is zero, only two things can be responsible:
You read real null bytes from the stream (unlikely)
Read does not read anything (in which case it returns 0 -- you should definitely be checking the return value)

bytes2 = sslStream.Read(buffer, 0, 4096); reads up to 4096 bytes into buffer, not exactly 4096 bytes. It blocks until at least one byte is read and returns the number of bytes read. So after the method call, buffer will have the same content as before the method call (e.g., filled with nulls), except for the first bytes2 bytes, which are the bytes received from the server.

Related

How do I keep reading data from my Socket to append my buffer

So I'm trying to send an image from my client to my server and I'm sending the entire image as a whole, meaning that I'm not splitting it up into chunks, I'm just sending the entire byte array as is.
CLIENT
private void SendImage(byte[] opcode, byte[] length, byte[] payload)
{
var packet = new byte[payload.Length + length.Length + 1];
Array.Copy(opcode, 0, packet, 0, 1);
//Set the length
Array.Copy(length, 0, packet, 1, length.Length);
Array.Copy(payload, 0, packet, 5, payload.Length);
_clientSocket.Send(packet);
}
This sends just fine, I'm using the OpCode 0x15 which will be interpreted by the server as "there is an image incoming". The length is the payload.Length which I've done this with
var length = BitConverter.GetBytes(myImage.Length);
So it occupies 4 bytes.
So my packet structure looks like this OpCode(1 byte), Length(4 bytes), Payload(imageBytes)
This method works just fine, it sends without any issues what so ever, I only included the code for it so that the next part will make sense.
SERVER
private byte[] _buffer = new byte[1024];
private void ReceiveCallback(IAsyncResult ar)
{
var client = (Socket)ar.AsyncState;
int received = client.EndReceive(ar);
//Temporary buffer
var dataBuf = new byte[received];
Array.Copy(_buffer, dataBuf, received);
switch (dataBuf[0])
{
//Received image
case 0x15:
//Read the packet header and check the length of the payload
var length = BitConverter.ToInt32(dataBuf.Skip(1).Take(4).ToArray(), 0);
//This will hold the bytes for the image
var imageBuffer = new byte[length];
//First incoming packet payload (image bytes)
var imgData = dataBuf.Skip(5).ToArray();
//Copy that into the buffer
Array.Copy(imgData, 0, imageBuffer, 0, imgData.Length);
var pos = imgData.Length;
//Keep reading bytes from the incoming stream
while (dataBuf.Length > 0)
{
imgData = new byte[1024];
client.Receive(imgData);
Array.Copy(imgData, 0, imageBuffer, pos, dataBuf.Length);
pos += 1024;
}
//This takes the bytes and creates a bitmap from it
AnotherViewModel.SetImage(imageBuffer);
break;
default:
Debug.WriteLine("Wat");
break;
}
client.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), client);
}
The issues I'm facing is that I don't know how to keep appending the incoming data to the imageBuffer because I want to receive the full image and not just the first 4 bytes and with my while loop I'm currently getting this exception
Destination array was not long enough. Check destIndex and length, and
the array's lower bounds.
Over at this line Array.Copy(imgData, 0, imageBuffer, pos, dataBuf.Length);
How do I properly read the entire image that the client sends to the server?

'If' statement on my client side is ignored by my function, even though it holds true

public static void SendMessage(RobotProperties properties)
{
string output = JsonConvert.SerializeObject(properties);
// Translate the passed message into ASCII and store it as a Byte array.
Byte[] data = Encoding.UTF8.GetBytes(output);
// Send the message to the connected TcpServer.
stream.Write(data, 0, data.Length);
Console.WriteLine("Sent:\n {0}", data);
// Receive the TcpServer.response.
// Buffer to store the response bytes.
data = new Byte[1000];
// Read the TcpServer response bytes into data buffer. stream.Read returns the number of bytes read which are stored into the bytes variable.
Int32 bytes = stream.Read(data, 0, data.Length);
string dataReceived = Encoding.Default.GetString(data);
Console.WriteLine("This was received: {0}", dataReceived);
if (dataReceived.Equals("Received") && count<50)
{
Console.WriteLine("Check if it gets here");
properties.x -= 1;
count++;
SendMessage(properties);
}
}
The count is initialized to 0. Although the client does receive the data i.e 'Received' and count is below 50, it doesn't go within the if statement and make the recursive call. What might be going wrong ?

Handle big bytes when receiving from serial port in c#

I am new in the serial port. Currently, my project is to extract data from the machine. I'm getting data via an event onDataReceive and the machine is sending bytes.
My problem is that the first wave of bytes seemed to be converted correctly to string but in the second batch of bytes, I got garbage data.
Screen Shot of the output(this is the output given by the multi-currency reader machine:
The garbage data is I think the Serial Nos.
Here is my code in onDataReceive method:
private void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
while (serialPort.BytesToRead > 0)
{
// Initialize a buffer to hold the received data
byte[] buffer = new byte[serialPort.ReadBufferSize];
//// There is no accurate method for checking how many bytes are read
//// unless you check the return from the Read method
int bytesRead = serialPort.Read(buffer, 0, buffer.Length);
String asd = System.Text.ASCIIEncoding.ASCII.GetString(buffer, 0, bytesRead);
//// For the example assume the data we are received is ASCII data.
tString += Encoding.ASCII.GetString(buffer, 0, bytesRead);
temp += System.Text.Encoding.Unicode.GetString(buffer, 0, bytesRead);
temp2 += System.Text.Encoding.UTF32.GetString(buffer, 0, bytesRead);
System.IO.File.WriteAllText(#"C:\OutputTextFiles\WriteLines.txt", tString);
System.IO.File.WriteAllText(#"C:\OutputTextFiles\WriteLines2.txt", temp);
System.IO.File.WriteAllText(#"C:\OutputTextFiles\WriteLines3.txt", temp2);
}
}
I'm trying to put the output with a txt file.
I hope someone could help me in my problem. Any tips and suggestions in data handling especially bytes?
Without knowing the size of serialPort.ReadBufferSize I can only suspect that your buffer is breaking the encoding bytes of your string. A character can be made of one or more bytes.
The trick is to read all of the bytes before decoding the string.
Try this example program:
var encoding = System.Text.Encoding.Unicode;
var message = "I am new in serial port. Currently my project is to extract data from machine.";
using (var ms = new MemoryStream(encoding.GetBytes(message)))
{
var bytes = new List<byte>();
var buffer = new byte[23];
var bytesRead = ms.Read(buffer, 0, buffer.Length);
while (bytesRead > 0)
{
Console.WriteLine(encoding.GetString(buffer, 0, bytesRead));
bytes.AddRange(buffer.Take(bytesRead));
bytesRead = ms.Read(buffer, 0, buffer.Length);
}
Console.WriteLine(encoding.GetString(bytes.ToArray(), 0, bytes.Count));
}
It will output the following:
I am new in�
猀攀爀椀愀氀 瀀漀爀琀�
. Currently�
洀礀 瀀爀漀樀攀挀琀 �
is to extra�
琀 搀愀琀愀 昀爀漀洀�
machine.
I am new in serial port. Currently my project is to extract data from machine.
The final line is correct because it uses all of the bytes to decode. The previous lines have errors because I've used a buffer size of 23 which breaks the string encoding.

Socket receiving data is not coming. I tested on hercules

I'm sending data to Lector device.
Normally I received data from device when I sending on hercules.
Hercules is returning "sRA eExtIn1 0 0 0".
The below code has waiting line stream.Read() function.
How can I getting data from device?
string responseData = null;
using (TcpClient client = new TcpClient("10.1.13.102", 2111))
{
using (NetworkStream stream = client.GetStream())
{
byte[] sentData = System.Text.Encoding.ASCII.GetBytes("<STX>sRN eExtIn1<ETX>");
stream.Write(sentData, 0, sentData.Length);
byte[] buffer = new byte[32];
int bytes;
if (client.Connected)
{
while ((bytes = stream.Read(buffer, 0, buffer.Length)) != 0)
{
for (int i = 0; i < bytes; i++)
{
responseData += (char)buffer[i];
}
}
}
}
}
The mistake you're making, and the other answer is also making, is assuming that stream.Read won't return until it has read 32 bytes. That is incorrect.
https://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.read(v=vs.110).aspx
This method reads data into the buffer parameter and returns the
number of bytes successfully read. If no data is available for
reading, the Read method returns 0. The Read operation reads as much
data as is available, up to the number of bytes specified by the size
parameter.
It will return when there is no data available to read or 32 bytes have been read, whichever comes first. So if, for example, the client is slow or the network very busy, the response may not have arrived yet when you call stream.Read. Consequently, there will be nothing to read so it will return 0 and you will exit, failing to read the data. In fact, you may have to call stream.Read any number of times to get the full 32 bytes if the network is very saturated and data is arriving a few bytes at a time (not likely with such a small packet, but you have to code it that way).
So your code needs to look like this (note the additional while loop):
using (TcpClient client = new TcpClient("10.1.13.102", 2111))
{
using (NetworkStream stream = client.GetStream())
{
byte[] sentData = System.Text.Encoding.ASCII.GetBytes("<STX>sRN eExtIn1<ETX>");
stream.Write(sentData, 0, sentData.Length);
byte[] buffer = new byte[32];
int bytes;
if (client.Connected)
{
int bytesRead = 0;
while (bytesRead < buffer.Length)
{
while ((bytes = stream.Read(buffer, 0, buffer.Length)) != 0)
{
for (int i = 0; i < bytes; i++)
{
responseData += (char)buffer[i];
}
bytesRead += bytes;
}
}
}
}
}
Thanks everybody.
I found solution of my question.
and tags should be describe as bytes. Like below.
byte[] byt = System.Text.Encoding.ASCII.GetBytes("sRN DItype");
stream.Write(STX, 0 , 1);
stream.Write(byt, 0, byt.Length);
stream.Write(ETX, 0, 1);
stream.Read(buffer, 0, buffer.Length);

Will C# NetworkStream.Read() wait until the specified amount of data is read?

In C/C++ read() on regular non-blocking network sockets will return immediately with the amount of data currently available in the buffer, up to the amount specified (so if we ask for 16 bytes and there are only 8 available at the moment, those 8 we'll get and it's up to us to call read() again and fetch all data).
In C# there's NetworkStream, which has built-in timeouts - does this mean that NetworkStream.Read() waits until either the timeout is reached or the amount of data requested is read, or will it give us any amount of data currently available in the buffer larger than 0 up to the amount requested (as the standard sockets do) even if there's time left?
It will read available data up to the number of bytes specified in the parameters, as described on MSDN, unless the stream is closed via timeout or other exception.
The Read operation reads as much data as is available, up to the number of bytes specified by the size parameter. If the remote host shuts down the connection, and all available data has been received, the Read method completes immediately and return zero bytes.
I solved it like this:
byte[] TotalData = new byte[0];
byte[] TempData = new byte[0];
using (TcpClient TCPClient = new TcpClient())
{
try
{
TCPClient.Connect(somehost, someport);
}
catch (Exception eee)
{
// Report the connection failed in some way if necessary
}
if (TCPClient.Connected)
{
using (NetworkStream clientStream = TCPClient.GetStream())
{
// You can reduce the size of the array if you know
// the data received is going to be small,
// don't forget to change it a little down too
byte[] TCPBuffer = new byte[524288];
int bytesRead = 0;
int loop = 0;
// Wait for data to begin coming in for up to 20 secs
while (!clientStream.DataAvailable && loop< 2000)
{
loop++;
Thread.Sleep(10);
}
// Keep reading until nothing comes for over 1 sec
while (clientStream.DataAvailable)
{
bytesRead = 0;
try
{
bytesRead = clientStream.Read(TCPBuffer, 0, 524288);
Array.Resize(ref TempData, bytesRead);
Array.Copy(TCPBuffer, TempData, bytesRead);
// Add data to TotalData
TotalData = JoinArrays(TotalData, TempData);
}
catch
{
break;
}
if (bytesRead == 0)
break;
Thread.Sleep(1000);
}
}
}
}
The JoinArrays() method:
byte[] JoinArrays(byte[] arrayA, byte[] arrayB)
{
byte[] outputBytes = new byte[arrayA.Length + arrayB.Length];
Buffer.BlockCopy(arrayA, 0, outputBytes, 0, arrayA.Length);
Buffer.BlockCopy(arrayB, 0, outputBytes, arrayA.Length, arrayB.Length);
return outputBytes;
}
The safe method is to use MemoryStream wich will make sure to wait and read all the stream to the memory , then u can use it as you like
public void SaveUserTemplate(Stream stream)
{
MemoryStream memoryStream = new MemoryStream();
stream.CopyTo(memoryStream);
memoryStream.Position = 0;
byte[] templatePathLength = new byte[4];
memoryStream.Read(templatePathLength, 0, templatePathLength.Length);
int nBytesTemplatePathLength = BitConverter.ToInt32(templatePathLength,0);
....
CopyTo function finally calls to this function:
github.com/microsoft/referencesource
private void InternalCopyTo(Stream destination, int bufferSize)
{
Contract.Requires(destination != null);
Contract.Requires(CanRead);
Contract.Requires(destination.CanWrite);
Contract.Requires(bufferSize > 0);
byte[] buffer = new byte[bufferSize];
int read;
while ((read = Read(buffer, 0, buffer.Length)) != 0)
destination.Write(buffer, 0, read);
}

Categories