C# virtual serial port timeoutexception on write - c#

i'm having a problem with virtual serial ports in C#: when i call the Write function, it automatically throws a TimeOutException, but the client receives the data.
It only happens with virtual ports (i'm using Free Virtual Serial Ports from HDDSoftware, with a bridge COM12<->COM13). I open COM12 with the Visual Studio and the COM13 with Hercules. The application throws the timeout exception but Hercules receives the message.
It doesn't matter if i set 1000ms or 1000000ms of Read/Write port timeout.
Thanks!!
using (SerialPort port = new SerialPort("COM13"))
{
// configure serial port
port.BaudRate = 9600;
port.DataBits = 8;
port.Parity = Parity.None;
port.StopBits = StopBits.One;
port.Open();
port.ReadTimeout = 10000;
byte[] buffer = Encoding.ASCII.GetBytes("HELLO WORLD");
try
{
port.Write(buffer, 0, buffer.Length);
}
catch(TimeoutException)
{
Console.WriteLine("Write timeout");
}
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss"));
try
{
byte[] buf = new byte[100];
port.Read(buf, 0, 1);
}
catch(IOException)
{
Console.WriteLine("Read timeout");
}
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss"));
}
After a few tests (putting the Write into a try-catch), the Read operation also throws a TimeOutException instantly.
This is what i get when run the test. It is supposed to be:
12:16:06
(Read timeout)
12:16:16

port.Write(buffer, offset, count);
It is up to the device driver to decide how to implement this. But all the ones I know follow the rule that the underlying WriteFile() call is allowed to return *lpNumberOfBytesWritten < nNumberOfBytesToWrite. Or to put it another way, the write is not "transactional".
A decent mental model is that Write() writes one byte from the buffer at a time, count times. At some point, entirely unpredictable when, writing one more byte will stall when the driver's transmit buffer fills up to capacity and cannot store another byte. Eventually triggering the exception.
So part of the buffer will still make it to the other end. You cannot tell what part from the SerialPort class. A time-out is a gross communication failure that's pretty hard to recover from. If that's a show-stopper then you need to consider writing one byte at a time (fine, serial ports are slow) or pay attention to WriteBufferSize - BytesToWrite to check if the buffer fits and implement your own timeout.

As Hans Passant said, it was a problem with the Virtual COM software. I tried with Virtual Serial Port from Eltima Software and worked fine!

Related

TCP transfer file works when server&client are running on 1 PC but corrupts when running on 2

So I'm trying to make a program which sends a file that I want to print from my client in my main PC, to my 2nd PC that runs the server and that is connected to a printer.
When I was testing my code I ran the client and server on my main pc and it worked fine. However, when I ran the client on my main PC and the server on my 2nd PC the file was corrupted and I'm not sure why.
Here's my Listener (I removed the parts that I thought were unnecessary):
void Listener()
{
//All of these strings and bools are filled correctly I just removed it because its long
string file="";
string size = "";
bool print;
Socket server = myList.AcceptSocket();
var output = File.Create(file);
Console.WriteLine("Client connected. Starting to receive the file");
int k = 0;
int read = 0;
byte[] buffer = new byte[long.Parse(size)];
NetworkStream stm = new NetworkStream(server);
while ((k = stm.Read(buffer, 0, buffer.Length-read)) > 0)
{
read += k;
}
output.Write(buffer, 0, buffer.Length);
output.Close();
if (print) { PrintFile(file); }
server.Close();
Thread.CurrentThread.Abort();
}
Here is the client code (I removed the parts that I thought were unnecessary):
void startClient()
{
FileInfo f = new FileInfo(file);
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
client.Connect(IPAddress.Parse("10.0.0.13"), 27015);
Console.WriteLine("Connected");
byte[] bytes = File.ReadAllBytes(file);
client.SendFile(file);
Console.WriteLine("File Sent");
client.Close();
}
Does anybody know how to solve this? Thanks in advance!
You don't apply the read offset to the buffer, starting to write at index 0 at every NetworkStream.Read() call. On local, or when testing with smaller files, this will work fine as everything will arrive in one Read(). On a real network or when handling larger files, you'll find that you need multiple Read() calls to read all data.
So change it to:
stm.Read(buffer, read, buffer.Length-read)
You also may want to reconsider reading the entire file in memory at once. You might want to write it to disk in the meantime, especially since allocating large arrays can cause an OutOfMemoryException way earlier than you expect.
Also consider using existing networking protocols as opposed to rolling your own. Besides this very basic issue, you're prone to running into many other common socket pitfalls.

Does Write send all bytes? (Serial Port)

Does Write method of SerialPort write all bytes it was told to?
I have this code to send data via serial port.
SerialPort port = new SerialPort(
"COM1", 9600, Parity.None, 8, StopBits.One);
// Open the port for communications
port.Open();
// Write bytes
byte[] bytes = Encoding.ASCII.GetBytes("Hello world from PC");
port.Write(bytes, 0, bytes.Length);
// Close the port
port.Close();
If I send string "Hello" the device connected to my PC via serial port receives it well. If I send string "Hello world from PC"
it only receives
first 16 bytes instead of 19.
Is there a way I can verify in code that all bytes were sent? Or it is problem of the hardware which is connected via serial port?
Yes, .Write is synchronous so all data is send before it returns. Anyway, 30 second timeout that you do would be more than enough, event if it wouldn't.
Normally all bytes are sent. Maybe the problem is at the receiving side.
To be sure that handshaking is turned off use this code, but I believe it is already the default:
serialPort.Handshake = Handshake.None;
I suspect the receiving side. It might be possible that the UART on the other side might not be fast enough to get the characters out of the buffer. Maybe you can try to add a small delays between parts of your message but that is only for troubleshooting, of course. Like so:
// Write bytes for test purpose
byte[] bytes = Encoding.ASCII.GetBytes("Hello world from PC");
port.Write(bytes, 0, 10);
Thread.Sleep(100); // small delay
port.Write(bytes, 10, 9); // next block
I had a similar problem.
I write an array of 20 bytes to the serial port which is connected to a wireless transmitter. After sending all bytes I need to switch back to receive mode.
Therefore it is necessary to exactly know when all bytes are physically written out of the serial port.
Unfortunately this is impossible under Windows since the buffer queries do not return the status of the physical chip buffer.
The solution for me was to send the data async with serialPort.BaseStream.WriteAsync
and then calculate the amount of transmit time by multiplying the number of bytes with the baudrate:
serialPort.BaseStream.WriteAsync(buffer,0,buffer.length);
int waittime = (int)((double)buffer.length * (10/(double)baudrate) + some_reserve);
Thread.Sleep(waittime);
the "10" means that one byte consists of 10 bits

Connect to a device through a serial port and send a command, but nothing is returned

I need to connect to a sensor through a serial port and read some data off it. I connect to it and send the command, but nothing is returned from the device, instead a Timeout exception is thrown. Similar questions here on stackoverflow use the OnDataReceived event, i tried that and it did not work. The parameters i used to initialize and the command i send work as expected on Putty.
-- what am i missing here
void Read()
{
SerialPort serialPort = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
try
{
serialPort.Handshake = Handshake.XOnXOff;
serialPort.Encoding = new ASCIIEncoding();
serialPort.ReadTimeout = 1000;
serialPort.WriteTimeout = 900;
serialPort.Open();
serialPort.WriteLine("TEMP");
MessageBox.Show("Reading");
MessageBox.Show(serialPort.ReadLine());
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
serialPort.Close();
}
}
Thank you
serialPort.Handshake = Handshake.XOnXOff;
Maybe that's correct, it is pretty unusual. But real devices almost always pay attention to the hardware handshake signals, in addition to an Xon/Xoff flow control protocol. The DTR (Data Terminal Ready) and RTS (Ready To Send) signals have to be turned on before the device is convinced that it is connected to a real computer. A program like Putty will always turn them on, your program does not.
Add these two required lines:
serialPort.RtsEnable = true;
serialPort.DtrEnable = true;
And ensure that the serialPort.NewLine property correctly matches the end-of-message character used by the device. Temporarily use ReadExisting() instead to avoid getting bitten by that detail, don't leave it that way.
I would suggest that the problem is with the encoding you're using. To check if that's the problem use a sniffer of your choice to see that the bytes transferred on your application are the same as on putty.
Only be sure that you're actually trying to read the bytes when using a sniffer because if you don't they won't be shown on the output.
If that doesn't show you anything you can try to change your ReadLine() method to ReadByte() to ensure that there's no problem with the reading type that you're using.
Serial port sniffers
http://www.serialmon.com/
virtual-serial-port.org/products/serialmonitor/?gclid=CInI2ZPL_bsCFaxr7Aod8S4A8w
www.hhdsoftware.com/device-monitoring-studio

SerialPort.DataReceived with USB TO COM cable act different then physical com

My C# desktop class library communicates with COM serial port.
The com is not real com, it is a USB to COM cable connected to USB to COM on another computer, the other computer uses a simulator to send data.
This solution works fine and then port opens successfully:
serialPort.Open();
if (serialPort.IsOpen)
{
serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
}
void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
var length = serialPort.BytesToRead;
byte[] buffer = new byte[length];
serialPort.Read(buffer, 0, length);
for (int i = 0; i < buffer.Length; i++)
{
System.IO.File.AppendAllText(#"c:\TestLogging.txt", string.Format("[Time = {0}] Data was received from serial port !", DateTime.Now)); }
}
The simulator send data all the time, and I receive the data in my class, BUT i dont receive it all the time, i see printing of 1 line every 30 seconds - although it suppose to print all the time!
What is weird - If i place break point in the line var length = .. then i see a the prints for the time i was halting on the break.. the data transferred seems to be "cached" and when i hit "Play" I receive the data but only for the time i was pausing the process.
I think you're too late registering the DataReceived eventhandler there. You should register to it before you open the port:
serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
serialPort.Open();
if (serialPort.IsOpen)
{
}
Try connecting your machines using HyperTerminal and check if the communication works. If it does, then it's your application's fault (double-check serialport settings). Otherwise it's probably the cable or the port itself.
Are you sure you're not getting any faulty data? Have you subscribed to SerialPort.ErrorReceived event handler? If you catch some SerialError.Frame errors there, then you probably have a faulty cable or the port is broken, or there are some conditions that are jamming the comunication (not vary likely but it can happen, for example if there is some strong source of power near by, for example an inverter).
OK, what is the problem ?
I am using USB to COM cable, and not true COM port.
The behavior of data receiving event from SerialPort is different.
I listen and catch the data event, but instead of getting array of bytes (as in real COM) - I receive every time a single byte (array in size of 1)..
Meaning: On DataReceived event when working with USB to COM port: i get this: 1-1-1-1-1-1 each DataReceived event give me 1 byte.
Real physical COM .DataReceived event give me: 5-30-42 etc.. Array of bytes
So my solution when working on USB to COM ports (some might call it "virtual COM port") I need to check if serialPort.BytesToRead is bigger then X, then i actually do
if (serialPort.BytesToRead > 2) //I dont want to get it 1-1-1.. want to get it atleast 2-2-2-2
serialPort.Read(buffer, 0, length);
Since serialPort.BytesToRead will tell me how many bytes are in current chunk, and Read. in my terms will get the buffer and clean it.

SerialPort ReadLine() after Thread.Sleep() goes crazy

I've been fighting with this issue for a day and I can't find answer for it.
I am trying to read data from GPS device trough COM port in Compact Framework C#. I am using SerialPort class (actually my own ComPort class boxing SerialPort, but it adds only two fields I need, nothing special).
Anyway, I am running while loop in a separate thread which reads line from the port, analyze NMEA data, print them, catch all exceptions and then I Sleep(200) the thread, because I need CPU for other threads... Without Sleep it works fine, but uses 100% CPU.. When I don't use Sleep after few minutes the output from COM port looks like this:
GPGSA,A,3,09,12,22,17,15,27,,,,,,,2.6,1.6,2.1*3F
GSA,A,3,09,12,22,17,15,27,,,,,,,2.6,1.6,2.1*3F
A,A,3,09,12,22,17,15,27,,,,,,,2.6,1.6,2.1*3F
,18,12,271,24,24,05,020,24,14,04,326,25,11,03,023,*76
A,3,09,12,22,17,15,27,,,,,,,2.6,1.6,2.1*3F
3,09,12,22,17,15,27,,,,,,,2.6,1.6,2.1*3F
09,12,22,17,15,27,,,,,,,2.6,1.6,2.1*3F
,12,22,17,15,27,,,,,,,2.6,1.6,2.1*3F
as you can see the same message is read few times but cut.
I wonder what I'm doing wrong...
My port configuration:
port.ReadBufferSize = 4096;
port.BaudRate = 4800;
port.DataBits = 8;
port.Parity = Parity.None;
port.StopBits = StopBits.One;
port.NewLine = "\r\n";
port.ReadTimeout = 1000;
port.ReceivedBytesThreshold = 100000;
And my reading function:
private void processGps(){
while (!closing)
{
//reconnect if needed
try
{
string sentence = port.ReadLine();
//here print the sentence
//analyze the sentence (this takes some time 50-100ms)
}
catch (TimeoutException)
{
Thread.Sleep(0);
}
catch (IOException ioex)
{
//handling IO exception (some info on the screen)
}
Thread.Sleep(200);
}
}
There is some more stuff in this function like reconnection if the device is lost etc., but it is not called when the GPS is connected properly. I was trying
port.DiscardInBuffer();
after some blocks of code (in TimeoutException, after read.)
Did anyone had similar problem? I really dont know what I'm doing wrong.. The only way to get rig of it is removing the last Sleep.
For all those who have similar problem. The first issue was about overflowing the buffer. I had 4096 size of buffer and the data was just flowing trough it so I was reading corrupted sentences. Now I read all buffer at once and analyze it. First sentence is sometimes corrupted, but the rest is ok.
The second thing was the device issue. Tom Tom MkII sometimes loses connection with the device. I had to restart the GPS and find it again in Bt devices list.
Regards
There's nothing in your post to say how you are doing handshaking.
Normally you would use software (XON/XOFF) or hardware (e.g. RTS/CTS) handshaking so that the serial port will tell the transmitting to stop when it is unable to receive more data. The handshaking configuration must (of course) match the configuration of the transmitting device.
If you fail to configure handshaking correctly, you may get away with it as long as you are processing the data fast enough - but when you have a Sleep, data may be lost.

Categories

Resources