Why would console display different received string than message box in c#? - c#

This is a follow up to my previous question. But it appears that for a reason I don't understand, the os is interpreting a received string differently than a message box is. This is apparent as when using message box.show function, it shows the correct string that was received. But the if then statement, the code for if the string equals what it does equal does not execute, and also the same string comes across as only system.byte it does not show in the console.
Here is the code:
SL_Click(object sender, EventArgs e)
{
try
{
TcpClient tcpclnt = new TcpClient();
tcpclnt.Connect(RecieveIP.Text, 8001); // receive the IP to listen from and port number for server.
MessageBox.Show("Connected");
Stream stm = tcpclnt.GetStream();
MessageBox.Show("Listening for information......");
byte[] bb = new byte[100];
int k = stm.Read(bb, 0, 100);
for (int i = 0; i < k; i++)
Console.Write(Convert.ToString(bb));
string atk = Encoding.ASCII.GetString(bb);
MessageBox.Show("Received Command " + atk);
if (atk == "g")
{
MessageBox.Show("working");
Search.RunWorkerAsync();
}
}
}
I'm leaving out the actual background worker code is it works ok in other implementations.
I am wondering why this may be? Thanks.

i don't know why you don't have it in a "while" loop or something but never mind that...
please try this:
byte[] bb = new byte[100];
int k = stm.Read(bb, 0, 100);
string data = Encoding.UTF8.GetString(bb.AsSpan(0, k ));
Console.WriteLine($"Data Received: {data}");//test
//if you want your check
//this will not work if your incoming data contains white space or other bytes that were converted.
if (data == "g" ||data.Contains("g"))//the .Contains can solve that prob, but a mix of letters containing "g" will trigger it
{
MessageBox.Show("working");
Search.RunWorkerAsync();
}
if your still having trouble please debug your incoming bytes and sent one.
make sure your not sending other bytes other the the "g" that you have send, if you use a different conversion method it might add additional bytes.
Consider checking your sent and received bytes!

Related

Server's socket blocking if no newline detected but client's socket not

While setting up a TCP server-client connection, I realized that the server receive function hangs if the client does not send an '\n', but the client does not block if the sever doesn't. I tried searching for an explanation without finding a proper answer, so I came here to ask for your help.
I am using the same function to exchange data for both server and client, but I don't know why it works for one and doesn't for the other...
Here is my function in C#:
public bool sendToClient(int i, string msg)
{
try
{
(clientSockets.ElementAt(i)).mSocket.Send(Encoding.ASCII.GetBytes(msg));
}
catch(Exception e)
{
Console.WriteLine(e.Data.ToString());
return false;
}
return true;
}
private string getMessageFromConnection(Socket s)
{
byte[] buff;
string msg = "";
int k;
do
{
buff = new byte[100];
k = s.Receive(buff, 100, SocketFlags.None);
msg += Encoding.ASCII.GetString(buff, 0, k);
} while (k >= 100);
return msg;
}
The sockets are simple SOCK_STREAM ones, and the clientSockets is a list containing Client objects containing each client info including their socket.
I understand that one solution would be to detect a particular character to end the message, but I would like to know the reason behind it because I also had this issue using C.
Thanks in advance.
Your while loop continues only as long as you're reading exactly 100 bytes, and it seems that you intend to use that to detect the end of a message.
This will fail if the message is exactly 100 or any multitude of 100 bytes (in which case it will append a subsequent message to it).
But even worse - there is no guarantee that the socket will return 100 bytes, even if there is data still on its way. Receive does not wait until the underlying buffer has reached 100 bytes, it will return whatever it has available at that point.
You're going to have to either include a header that indicates the message length, or have a terminator character that indicates the end of the message.

COM: Device only sends data when things are changing. How to deal with that?

So I want to connect to a device via Serial that only sends data when things are changing with the settings on the device (a measuring device).
I use C# and .Net's SerialPort.
I am able to read data and it looks kind of good. But there are a few problems I encountered.
I realized my reading- method (ReadExistingData()) so that it will constantly use the SerialDataReceivedEventHandler when there's new data.
Unfortunately, when I read it like that (probably because of varying package sizes) it will read very chaotically and thus I need to "catch" the first initiating byte (here it's 0xA5).
That means, I always check whether the byte I just received is a 0xA5 and if it is, I read the rest.
But I feel like that way I am missing some commands my device sends me and thats why I cant display the data consistently right, only from time to time.
On a side note: The device sends the device time and a value. The value is delayed and kind of unaccurate, but the time is always right on spot. The other parameters it sends are always weirded out and dont seem to be recognized and thus changed at all.
To display data I use the console for testing purposes, and the whole construct seems to be very reactive to Console outputs.
Here's a little code snippet:
class Device
{
private int stdMessageLengthInBytes = 5;
public DeviceData processedData;
byte[] dataBuffer;
int receivedMessages = 0;
public Device()
{
// Initialize BaseClass (SerialPort derivative)
this.port = new System.IO.Ports.SerialPort();
// Initialize Device
this.data = new byte[stdMessageLengthInBytes];
this.processedData = new P8005_Data();
dataBuffer = new byte[stdMessageLengthInBytes];
}
// Is supposed to read the data from serial port
protected override void ReadExistingData()
{
// Check whether buffer is empty -> Try to catch a 0xA5
if (dataBuffer[0] == 0x00)
{
port.Read(dataBuffer, 0, 1);
}
// If no 0xA5 was catched, restart
if (dataBuffer[0] != 0xA5)
{
dataBuffer = new byte[stdMessageLengthInBytes]; // Reset buffer
return;
}
// Read next byte -> Command byte
port.Read(dataBuffer, 1, 1);
// If command was empty, restart
if (dataBuffer[1] == 0x00)
{
dataBuffer = new byte[stdMessageLengthInBytes]; // Reset buffer
return;
}
// If its time that is communicated: Read 3 bytes
if (dataBuffer[1] == 0x06)
{
// 4 ms delay seems to be needed otherwise it wont function correctly somehow
System.Threading.Thread.Sleep(5);
port.Read(dataBuffer, 2, 3);
// Write buffer to actual raw data byte array
this.data = dataBuffer;
dataBuffer = new byte[stdMessageLengthInBytes]; // Reset buffer
}
// Otherwise: Just read 2 bytes
System.Threading.Thread.Sleep(5); // Needed delay
port.Read(dataBuffer, 2, 2);
// Write buffer to actual raw data byte array
this.data = dataBuffer;
dataBuffer = new byte[stdMessageLengthInBytes]; // Reset buffer
}
// Method called by SerialDataReceivedEventHandler
protected override void DataReceivedOnComPort(object sender, SerialDataReceivedEventArgs e)
{
bool valid = false;
ReadExistingData(); // Read data from COM- Port
lock (processedData)
{
switch (data[1]) // Check command byte
{
// Time (3 btyes)
case (0x06):
processedData.currentTime = String.Format("{0:D2}:{1:D2}:{2:D2}", DecodeBcd(data[2]), DecodeBcd(data[3]), DecodeBcd(data[4]));
valid = true;
receivedMessages++;
break;
// Value (2 bytes)
case (0x0D):
double val = 0;
val += DecodeBcd(data[2]) * 100;
val += DecodeBcd(data[3]);
val /= 10;
processedData.currentValue = val;
valid = true;
receivedMessages++;
break;
// ... here are various other hex- code that represent a command from the device (2 btyes)
default:
valid = false;
break;
}
}
// only to check when
if (valid)
{
Console.WriteLine("Received Valid Messages: {0}", receivedMessages);
ConsoleOutput();
}
}
}
On a note: The initialization of the port happens in another method from the base class and works fine.
Is there anything I am missing? How to deal with something like that? Are there any improvements that would help improving my performance? I thought about threading with locks, but I dont think that is the solution somehow... Or maybe everything is just a console problem?
EDIT:
I know changed my code (as #jdweng suggested) so that I put everything in a buffer (basically List<byte> mainBuffer. Then, I take all bytes in the buffer whenever its possbile and work with them, skimming it for 0xA5. When one is found, I read the command and determine how long the "message" has to be according to it (Time -> +3 bytes, Data -> +2 bytes, Other -> +1 byte). Then I can work off those messages (I put them into a List<byte[]>) and determine my output to my screen.
However, even after outsourcing the chopping up into messages and processing the messages, I still seem to either miss some messages, since some action are just not registered and have a big delay, or my processing is wrong. What I can think of is that because I lock my mainBuffer maybe some data isnt written to it.
Is this really this time critical? There is a software that comes with the device and it doesnt seem to have such big problems with delay and slightly wrong values...
Since you don't have the exact specs and/or an unreliable connection (which with serial data has to be expected) you need to sync to the 0xa5 at every message. I would just run every single byte you receive through a parser while keeping the state of the currently received message.
Make sure you validate your input since there are a bunch of things that can go wrong if you get messed up serial data. For example if there is an 0xa5 in the other message types, you might miss your next message. To prevent that I strongly recommend to either get to the specs if possible or code more logic based on data observations.
private const int MESSAGE_LENGTH = 5;
private const int VALUE_COMMAND = 0x0D;
private const int VALUE_SIZE = 4;
private const int TIME_COMMAND = 0x06;
private const int TIME_SIZE = 5;
private byte[] _message = new byte[MESSAGE_LENGTH];
private int _messagePos = 0;
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
var data = new byte[_serialPort.BytesToRead];
_serialPort.Read(data, 0, data.Length);
foreach (var b in data)
{
_message[_messagePos] = b;
if (_messagePos == 0 && b != 0xa5)
continue;
++_messagePos;
if (_messagePos > 2) // if command byte present, process command of any size
ProcessCommand(_message[1]);
}
}
private void ProcessCommand(byte command)
{
if (_messagePos == VALUE_SIZE && command == VALUE_COMMAND)
{
// parse value...
_messagePos = 0;
}
else if (_messagePos == TIME_SIZE && _message[1] == TIME_COMMAND)
{
// parse time...
_messagePos = 0;
}
}

Windows phone 7: Socket does not returns the whole image from server

I am working on the TCP Socket in windows phone.
i created one application in that i have to receive the image from server.
for that i converted the image in to array of bytes to transfer to windows phone.
But, some times windows phone gets the whole Byte array and some times not getting the whole byte Array of image.
So, here i coded that,
public void ReceiveMessage()
{
var responseListener = new SocketAsyncEventArgs();
responseListener.Completed += OnMessageReceivedFromServer;
var responseBuffer = new byte[bufferSize];
responseListener.SetBuffer(responseBuffer, 0, bufferSize);
connection.ReceiveAsync(responseListener);
}
And after received the message i called the OnMessageReceivedFromServer.
in that
public void OnMessageReceivedFromServer(object sender, SocketAsyncEventArgs e)
{
// Convert the received message into a string
var message = Encoding.UTF8.GetString(e.Buffer, 0, e.BytesTransferred);
//trailingmessage is the string declared with null.
//it will store the message if the message is greater than the bufferSize.
trailingMessage = trailingMessage + message;
//This checks wheather the message is remaining or not.
//if yes then it will again receives the message until it resumes.
if (e.BytesTransferred > 0 && e.BytesTransferred == bufferSize)
{
ReceiveMessage();
}
else
{
receivedstring = trailingMessage;
trailingMessage = null;
ReceiveMessage();
onMsg.Invoke(receivedstring);
}
}
You can not safely convert byte array to string and then get the original bytes (using Encoding.GetString, Encoding.GetBytes).
Here is a code showing it wouldn't work
byte[] buf = { 255, 255, 255 };
var newBuf = Encoding.UTF8.GetBytes(Encoding.UTF8.GetString(buf));
newbuf's content: 239,191,189,239,191,189,239,191,189
Instead of using a string to store your image use a List of bytes:
List<byte> trailingBuffer = new List<byte>();
The add the received bytes to this list:
public void OnMessageReceivedFromServer(object sender, SocketAsyncEventArgs e)
{
for(int i = 0; i < e.BytesTransferred; i++)
{
trailingBuffer.Add(e.Buffer[i]);
}
// handling of complete / non-complete message ...
}
This test:
if (e.BytesTransferred > 0 && e.BytesTransferred == bufferSize)
{
ReceiveMessage();
}
is not valid. It is perfectly legitimate to receive the data 1 byte at a time (even if the other end send all the data at once) - in which case yes you got data (the > 0), but you did not get a full buffer (the == bufferSize). This is simply how a stream works (and sockets typically operate as a stream). You need to either keep looping until the end of the stream (e.BytesTransferred <= 0), or (usually if you want to send several messages on the same socket) you need to implement some form of "framing" - most commonly (since this is binary) by simply writing the expected number of bytes into the stream first, and then read exactly that amount.
See also: http://marcgravell.blogspot.com/2013/02/how-many-ways-can-you-mess-up-io.html

problems about getting repeated sockets which i do not intend

I'm working on a messenger program using c#, and have some issues.
The server, client has three connections(each for chatting, filetrans, cardgames).
For the first, and second connection, it's working just fine.
But the problem occurred on the third one, which handles less amount of packet types compared to the first two sockets.
It's not about not receiving the packet or not getting a connection, but it's getting(or sending)
more then one(which I intend to send) packets at a time. The server log keeps on saying that
on one click, the server receives about 3~20 same packets and sends them to the targeted client.
Before my partial codes for the third connection, I'll explain how this thing is suppose to work.
The difference between connection1,2 and connection3(which is making this issue) is only the time
when I make the connection. The 1,2 makes it's connection on the main form's form_load function, and works fine.
The connection 3 makes connection when I load the gaming form(not the main form). Also, the first
two socket's listening thread are on the main form, and the third has it's listening thread on it's
own form. That's the only difference that I can find. The connections, and listening threads are
the very same. Here are my codes for the gaming form.
public void GPACKET() //A Thread function for receiving packets from the server
{
int read = 0;
while (isGameTcpClientOnline)
{
try
{
read = 0;
read = gameNetStream.Read(greceiveBuffer, 0, 1024 * 4);
if (read == 0)
{
isGameTcpClientOnline = false;
break;
}
}
catch
{
isGameTcpClientOnline = false;
gameNetStream = null;
}
Packet.Packet packet = (Packet.Packet)Packet.Packet.Desirialize(greceiveBuffer);
switch ((int)packet.Type)
{
case (int)PacketType.gameInit:
{
gameinit = (GameInit)Packet.Packet.Desirialize(greceiveBuffer);
//codes for handling the datas from the packet...
break;
}
case (int)PacketType.gamepacket:
{
gp = (GamePacket)Packet.Packet.Desirialize(greceiveBuffer);
//codes for handling the datas from the packet...
break;
}
}
}
}
public void setPacket(bool turn) //makes the packet, and sends it to the server..
{
if (turn)
turnSetting(false);
else
turnSetting(true);
gps = new GamePacket();
gps.Type = (int)PacketType.gamepacket;
gps.isFirstPacket = false;
gps.sym = symbol;
gps.ccapacity = cardCapacity;
gps.currentList = current_list[0].Tag.ToString();
gps.isturn = turn;
gps.opname = opid;
List<string> tempList = new List<string>();
foreach (PictureBox pb in my_list)
{
tempList.Add(pb.Image.Tag.ToString());
}
gps.img_list = tempList;
Packet.Packet.Serialize(gps).CopyTo(this.gsendBuffer, 0);
this.Send();
label5.Text = symbol + ", " + current_list[0].Tag.ToString();
}
public void Send() //actually this part sends the Packet through the netstream.
{
gameNetStream.Write(this.gsendBuffer, 0, this.gsendBuffer.Length);
gameNetStream.Flush();
for (int j = 0; j < 1024 * 4; j++)
{
this.gsendBuffer[j] = 0;
}
}
I really don't know why I'm having this problem.
Is it about the connection point? or is it about the receiving point? Or is it about the sending point? If I establish this connection on the same place to the connection1,2(which is on the main form. If i do this, I should make the "GPACKET" function running on the main form as well)?
This looks like a classic "assume we read an entire packet", where by "packet" here I mean your logical message, not the underlying transport packet. For example:
read = gameNetStream.Read(greceiveBuffer, 0, 1024 * 4);
...
Packet.Packet packet = (Packet.Packet)Packet.Packet.Desirialize(greceiveBuffer);
Firstly, it strikes me as very off that read wouldn't be needed in Desirialize, but: what makes you think we read an entire packet? we could have read:
one entire packet (only)
half of one packet
one byte
three packets
the last 2 bytes of one packet, 1 entire packet, and the first 5 bytes of a third packet
TCP is just a stream; all that Read is guaranteed to give you is "at least 1 byte and at most {count} bytes, or an EOF". It is very unusual that calls to Write would map anything like the calls to Read. It is your job to understand the protocol, and decide how much data to buffer, and then how much of that buffer to treat as one packet vs holding them back for the next packet(s).
See also: How many ways can you mess up IO?, in partuclar "Network packets: what you send is not (usually) what you get".
To fill exactly a 4096 byte buffer:
int expected = 4096, offset = 0, read;
while(expected != 0 &&
(read = gameNetStream.Read(greceiveBuffer, offset, expected)) > 0)
{
offset += read;
expected -= read;
}
if(expected != 0) throw new EndOfStreamException();

SerialPort class and DataReceived event... Getting bytes. Use ReadLine or ReadExisting? Any examples?

I would like to send and receive bytes over serial. My receiver should get the bytes asynchronously. I've written the small example below that appears to work, but it leaves me with an unsettled feeling.
Should I really be using WriteLine, ReadLine? As it's written now, is it possible that the code in the event handler m_port_DataReceived is going to be called for each and every byte? That was my understanding of the event "DataReceived"; perhaps I'm wrong. Does ReadLine block until it sees an end of line character?
Should I somehow use the "if (e.EventType == SerialData.Eof)" construct in the event handler? You can see I have it commented out. I tried it and could not get it to work. When would one expect a SerialData.Eof? My idea was that I could wait before all bytes were present before calling "ReadExisting". However, the "if" statement never evaluated to true. Force the code to go to ReadExisting did correctly read all the bytes however.
In general, what's the best way to set up my code to receive bytes coming over the serial port? The sender will be sending small chunks of bytes every 125 msecs, but will not be sending special characters. The packets of bytes are spaced out in time, so I don't think there's a problem of mixing packets together. More the problem is, "once you see one byte, go read everything, as long as you wait a very short time, you'll get everything". Given this scenario, is there a preferred way?
Thanks in advance,
Dave
public class SerialPortController
{
SerialPort m_port;
public SerialPortController(bool server)
{
if (server)
{
m_port = new SerialPort("COM4");
m_port.BaudRate = 115200;
m_port.Open();
byte[] sillyBytes = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 };
ASCIIEncoding encoding = new ASCIIEncoding();
string output_string = encoding.GetString(sillyBytes);
m_port.WriteLine(output_string);
//m_port.Write(sillyBytes, 0, 8);
}
else
{
m_port = new SerialPort("COM5");
m_port.DataReceived += new SerialDataReceivedEventHandler(m_port_DataReceived);
m_port.BaudRate = 115200;
m_port.Open();
}
int character = Console.Read();
}
void m_port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
//if (e.EventType == SerialData.Eof)
{
// string answer = m_port.ReadExisting();
string answer = m_port.ReadLine();
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] byte_answer = encoding.GetBytes(answer);
}
}
}
ThereĀ“s and example at MSDN which shows simple use of this.
And it used ReadExisting instead of ReadLine.
Also from the docs:
The DataReceived event is not guaranteed to be raised for every byte received. Use the BytesToRead property to determine how much data is left to be read in the buffer.
private static void DataReceviedHandler(
object sender,
SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
Console.WriteLine("Data Received:");
Console.Write(indata);
}

Categories