Win API serial port need to wait after initialization - c++

I have a following problem. I have a serial port device that is supposed to communicate with a computer. In fact it is Arduino Due board but i don't think it is related.
I use CreateFile to open the port, and then set the parameters using GetCommState()&SetCommState() and GetCommTimeouts()&SetCommTimeouts().
The port is opened correctly - no problem there. But at this point I want to check whether the device is connected. So I send a specific message. The device is supposed to respond in a certain way so that I know it is connected.
Now to the problem: It only works if put Sleep(1000) after Creating the port (before sending the handshake request). It looks as if the WinAPI needs some time before it can begin to use the port. Because the Sleep solution is not generally usable I need to find some alternative...
By it doesn't work I mean ReadFile times out. It times out even if the timeout is set to something like 5 seconds - note that the Sleep interval is only one second. So it looks like the handshake request is not even sent. If I set timeout to 1 second and Sleep interval to one second, it works. If I set timeout to 5 seconds but there's no Sleep it doesn't work. See the problem?
I am going to try some NetworkMonitor, but I'm kinda sure the problem is not with the device...

OK, I might have searched a little more before posting this question.
The thing is that Arduino restarts itself when you open a connection from your PC.
When you use a terminal you connect first and write a few seconds later so that the Arduino board has enough time to boot up and you won't notice the thing. Which is what confused me enough to write the question.
There are 3 solutions to this, only 2 of which it makes sense to mention at all:
1) the solution I used without knowing all this (you wait about a second for the board to boot up again...)
2) you disable auto-reset by modifying your Arduino board
Both of them are stupid if you ask me, there should be a switch or a flash variable to do this...

Related

mbed socket connection takes a long time

I'm fighting with my Mbed controller and it's winning :/
Part of my code below:
eth.connect();
pc.printf("ethernet OK");
sock.set_blocking(false,200);
pc.printf(" socket setting OK ");
sock.connect("192.168.1.100", 80);
pc.printf("GO! GO! GO!");
conn = sock.is_connected();
When the server is on I can connect with socket and there is no problem. But when I shut my server down, my program wait in sock.connect(...) line for a long time and then it moves forward. I want it to move forward, but I don't want to wait such a long time :/
I found that I should change socket setting from blocking to non-blocking, and timeout from default=1500 to less. I changed it everywhere I could:
- Part of my socket.h library:void set_blocking(bool blocking, unsigned int timeout=200);
- Part of my socket.cpp library:Socket::Socket() : _sock_fd(-1), _blocking(false), _timeout(200)
And still nothing. It wait about 17-18sec, but I would like to change it to max. 1-2sec.
I would be glad, if you give me an any tip :)
Assuming you are using mbed OS, set the socket to blocking and set the timeout to whatever you think is appropriate. No modifications are necessary. The method syntax can be seen here.
However, I am having trouble reproducing your issue. Can you use a debugger and confirm if the application is hanging at this line - https://github.com/ARMmbed/mbed-os/blob/533e6f0febb5ea582a61f0c8aaf686c70333524f/features/netsocket/TCPSocket.cpp#L57?
marshmallow's suggestion should be fine.
Theoretically you could also try and set the TCP_SYNMAXRTX macro to something lower. It might have some other unforeseen consequences though (which I'm not sure off, as I don't know much about LwIP).
Firstly I need to say, that TCP_SYNMAXRTX changing is something, what can really help, it helped me, but not at all. In my case the important was to change mbed OS to the latest version. In previous there was libraries with socket settings, but actually they work properly since mbed OS contains EthernetInterface and others libraries (you shouldn't import it as external library).
Thank you for your time and goodwill! :)

About socket connection timeout in C++ (UNIX)

I have been working to put a 15 seconds timeout to a socket to avoid it to be blocked. So i configured it as non-blocking, then used select function, and works fine... when the computer is connected to a network!
If computer is disconnected from the network (for example, if Wi-Fi signal is turned off, or if you emove the ethernet plug), when I call connect function it returns inmediatly the "Network is unreachable" error.
Since I have a loop to get it reconnected if something like this happens, it is trying to connect MANY times, so I'm getting log files of gigabytes.
So, what I want is to set some kind of timeout for that too. It's not a timeout actually, but I want it to wait 15 seconds until it tries to connect again to avoid this problem. I was wrong when I thought that the timeout i have set as explained in paragraph 1 would fix this too. How can I make this then?
You could test the errno and sleep if it's ENETUNREACH.

ctb::SerialPort - time-out in Write()

I'm writing program that should control a piece of scientific hardware over COM-port. The program itself is written in wxWidgets and uses ctb library. To test, it before I connect it to 300k€ equipment, I use com0com (Null-modem emulator) to forward COM2 port. To emulate my hardware I use wxTerminal (COM3). Altogether it works nice. One can debug not only in VS or DB but also see the whole data transfer in wxTerminal.
Now to my problem. I use to send data to COM-port ctb::SerialPort::Write() function.
device->Write( (char*)line.c_str(), line.size() );
However, if I disconnect the connection on the side of wxTerminal (i.e. COM2->NULL) than program hangs in this function.
It's obvious that I should add some function to test if my equipment is still there, but to do it I need to send data-packet to it and expect some answer. So I'm back to the Write().
"Just in case" I've also tried ctb::IOBase::Writev (char ∗ buf, size_t len, unsigned int timeout_in_ms) with timeout set to 100ms and I've still got program hanging in the same line. It's actually expected behavior as in this case timeout means only that the connection line is blocked till whole buffer is transferred or timeout is reached.
Connecting of wxTerminal to COM3 leads to un-freezing of debugger or stand-alone program. The Sun is shining, the birds are singing.
Can somebody give me a hint how to overcome my problem? I'd appreciate if comments would be restrained to wxWidgets-world - I really do not want to re-write whole program with other toolkit.
If you COM port library does not provide effective timeouts on write block, (presumably because of hardware flow-control), you could implement your own by threading off the write. You could use a couple of events/semaphores/condvar/whatever. One to signal to the thread that there is something in a buffer to send and another that you can wait on with a timeout that is signaled by the thread after it has sent the buffer. If the 'ack' wait times out, your COM port is stuck and you can pop up some 'Check cable' messageBox. I don't know what other calls your port lib supports, so I don't know how you could implement flushes/retries.

Should I implement my own TCP/IP socket timeouts?

The software I'm working on needs to be able to connect to many servers in a short period of time, using TCP/IP. The software runs under Win32. If a server does not respond, I want to be able to quickly continue with the next server in the list.
Sometimes when a remote server does not respond, I get a connection timeout error after roughly 20 seconds. Often the timeout comes quicker.
My problem is that these 20 seconds hurts the performance of my software, and I would like my software to give up sooner (after say 5 seconds). I assume that the TCP/IP stack (?) in Windows automatically adjusts the timeout based on some parameters?
Is it sane to override this timeout in my application, and close the socket if I'm unable to connect within X seconds?
(It's probably irrelevant, but the app is built using C++ and uses I/O completion ports for asynchronous network communication)
If you use IO completion ports and async operations, why do you need to wait for a connect to complete before continuing with the next server on the list? Use ConnectEx and pass in an overlapped structure. This way the individual server connect time will no add up, the total connect time is the max server connect time not the sum.
On Linux you can
int syncnt = 1;
int syncnt_sz = sizeof(syncnt);
setsockopt(sockfd, IPPROTO_TCP, TCP_SYNCNT, &syncnt, syncnt_sz);
to reduce (or increase) the number of SYN retries per connect per socket. Unfortunately, it's not portable to Windows.
As for your proposed solution: closing a socket while it is still in connecting state should be fine, and it's probably the easiest way. But since it sounds like you're already using asynchronous completions, can you simply try to open four connections at a time? If all four time out, at least it will only take 20 seconds instead of 80.
All configurable TCP/IP parameters for Windows are here
See TcpMaxConnectRetransmissions
You might consider trying to open many connections at once (each with its own socket), and then work with the one that responds first. The others can be closed.
You could do this with non-blocking open calls, or with blocking calls and threads. Then the lag waiting for a connection to open shouldn't be any more than is minimally nessecary.
You have to be careful when you override the socket timeout. If you are too aggressive and attempt to connect to many servers very quickly then the windows TCP/IP stack will assume your application is an internet worm and throttle it down. If this happens, then the performance of your application will become even worse.
The details of when exactly the throttling back occurs is not advertised, but the timeout you propose ( 5 seconds ) should be OK, in my experience.
The details that are available about this can be found here

GetQueuedCompletionStatus stops reading a serial port

I have a device that generates messages over a serial port. When I reboot the device, the IO Completion Port stops reading bytes.
The code is calls GetQueuedCompletionStatus():
BOOL bRet = GetQueuedCompletionStatus(
m_hCompletionPort,
&dwBytesTransferred,
&dwCompletionKey,
&pOverlapped,
INFINITE);
PortMon looks like:
...
IRP_MJ_WRITE Serial1 SUCCESS LENGTH: 7 REBOOT.
IRP_MJ_READ Serial1 CANCELLED LENGTH: 1
Logging shows the following result:
bRet=true, dwBytesTransferred=7, pOverlapped=0x0202B028, GetLastError()=997
(sleep forever)
Is there any way to detect this failure and reestablish communications?
I can monitor a heat beat and close/reopen the serial port, but it doesn't seem right that the windows API allows serial communications to silently drop like this.
If you do WaitForSingleObject on the handle for the serial port that you opened to start reading data, does the handle become signalled when the device is rebooted? Maybe this is a way to tell when you need to open the port again?
IO Completion Ports can certainly handle this case without problem. You don't need to close and reopen the device.
The most likely problem in this case is that you have an error on the line (caused by the device reset) that you have not cleared using ClearCommError().
You need to use SetCommState() and SetCommTimeouts() appropriately for your device up front. In the DCB you pass to SetCommState(), you need to set fAbortOnError. If you do dequeue an error you need to call ClearCommError() before you requeue another read.
RE: janm (I can't seem to add a comment to your answer sorry)
I did try setting various flags, including the DCB's fAbortOnError, but GetQueuedCompletionStatus() would still wait infinitely. I also tried periodically timing out the call, and checking the serial port for errors. The serial port always looked fine, yet the disconnection would still permanently break the IO Completion Port. The device rebooting probably creates a transient error state... I say probably, because I've never been able to detect it!
A fellow developer also had a crack at this problem, and they too failed. So we just rewrote the code to use overlapped serial port reads, and now it works fine.
There is probably something, somewhere that we missed... in the end we wasted more time trying to solve the mystery than it took to rewrite the code.