Hi Everyone
I just finished porting my project from MQX 4.0 to MQX 4.1. We are using a custom platform that is very close to TWRK60M512 tower board with some minor pinout differences.
I have a TCP client application (Modbus protocol client) which is working perfectly on the MQX4.0.
The client app is quite simple:
1. Connect to 6 servers using 6 sockets
2. Read the data (modbus tcp data) from those sockets
When i tired to run the same app after porting it (replacing the old MQX datatypes with the C99 style ones) and running it i get a really strange behaviour.
I attach a wireshark PCAP file which can explain it way better then with words. Basically after i Open 6 sockets and start reading the data, RTCS sends TCP RESET to the server.
So i made a test. I have called connect() 6 times with 6 different sockets and paused the debugger right after that. All 6 sockets are opened, see attached picture.
After that, i have performed one Modbus TCP request to only the 1st socket. But the other 4 sockets were issued a TCP RESET command from RTCS and it is visible on the captured as well.
Can anyone shed any light on what might be going on there? I know for sure there are no stack smashed (i increased the stacks and it checked with TAD plugin, all at around 40%-65%).
Any help would be greatly appreciated.
Also, here are the socket options that i set to all of those 6 sockets:
VOID MBPTCPSetSockOptions(SOCKET iSocket)
{
UINT option = 0;
option = 5000;
ULONG retval = RTCS_OK;
retval |= setsockopt(iSocket, SOL_TCP, OPT_CONNECT_TIMEOUT, &option, sizeof(option));
option = 400; //380
retval |= setsockopt(iSocket, SOL_TCP, OPT_RBSIZE, &option, sizeof(option));
option = 400; //380
retval |= setsockopt(iSocket, SOL_TCP, OPT_TBSIZE, &option, sizeof(option));
option = 1;
retval |= setsockopt(iSocket, SOL_TCP, OPT_NO_NAGLE_ALGORITHM, &option, sizeof(option));
option = 0;
retval |= setsockopt(iSocket, SOL_TCP, OPT_RECEIVE_NOWAIT, &option, sizeof(option));
option = 1;
retval |= setsockopt(iSocket, SOL_TCP, OPT_RECEIVE_PUSH, &option, sizeof(option));
option = 0;
retval |= setsockopt(iSocket, SOL_TCP, OPT_SEND_NOWAIT, &option, sizeof(option));
option = 1;
retval |= setsockopt(iSocket, SOL_TCP, OPT_SEND_PUSH, &option, sizeof(option));
option = 0;
//retval |= setsockopt(iSocket, SOL_TCP, OPT_TIMEWAIT_TIMEOUT, &option, sizeof(option));
option = 100;
retval |= setsockopt(iSocket, SOL_TCP, OPT_RECEIVE_TIMEOUT, &option, sizeof(option));
option = 30; //30 seconds keep alive
retval |= setsockopt(iSocket, SOL_TCP, OPT_KEEPALIVE, &option, sizeof(option));
if(RTCS_OK != retval)
{
TASK_BLOCK();
}
}
Thanks in advance
I found the problem and as always it was in our code
However there is one interesting observation:
Here is the code i use:
SOCKET iClientSocket[1] = SocketDescriptor i got from socket() function call
at this point connect() was called as well
recieving function:
SOCKET iResultSocket ;
while(!)
{
iResultSocket = RTCS_selectset( iClientSocket , 1, 10);
if (RTCS_SOCKET_ERROR == iResultSocket)
{
//hadle error close the socket
}
else
{
if(SELECT_TIMED_OUT == iResultSocket)
{
//sleep 1 MS and continue to the top of the loop
}
else
{
READ FROM THE SOCKET HERE.
And this was the problem, since RTCS_selectset was returning a different socket value then the value of iClientSocket[0].
When i put the check here to see that iResultSocket == iClientSocket[0] and then do a read, problem disappeared
}
}
Can anyone on the MQX team please confirm that there is an issue with RTCS_selectset?
Thank you
Hi,
I wonder if you enable RTCSCFG_SOCKET_OWNERSHIP ? The described issue might happen if RTCSCFG_SOCKET_OWNERSHIP is TRUE and the task is the owner of more sockets. A task is an owner of a socket if it creates it (a call to socket()).
Just a side note, current implementation of RTCS_selectset() function cannot distinguish between readability/writeability, so a socket can unblock RTCS_selectset() when an ACK has been received and the send buffer is empty (= it is writeable). So, perhaps you may need to put also a timeout for recv() and send() calls (a received ACK might unblock RTCS_select, and if your code calls recv() then, socket might not have any data for reading and recv() might block).
We re-designed select functionality for next version of MQX, so that MQX RTCS will support standard BSD-like select() on sockets. It is able to choose between read/write-abiltiy. For backward compatibility, RTCS_selectset() function will still be supported, but inside the stack, it will be implemented using the new select() function.
-Martin
Hi Martin
Thank you for your reply
I have checked and the RTCSCFG_SOCKET_OWNERSHIP is disabled.
Unblocking of RTCS_select because of a write is probably what is happening since i have recv and send in different tasks.