• AVR Freaks

Helpful ReplyHot![SOLVED] TCP Socket reuse issue

Author
luca.leoncavallo@gaengineering.com
Starting Member
  • Total Posts : 36
  • Reward points : 0
  • Joined: 2015/02/12 03:52:15
  • Location: 0
  • Status: offline
2020/02/24 02:31:20 (permalink)
0

[SOLVED] TCP Socket reuse issue

Hi
 
I'm working with PIC32MZ on a custom board and we use modbus over TCP.  The code is written using the modbus demo for PIC24 as a starting base.
 
The firmware works but we have problems with socket. If, for istance, i define 5 sockets as the maximum to use it happen that if the modbus client connect and disconnect five times then every other connection is impossibile!!!
It seems that the socket after disconnection are not properly closed and then NOT reused.
 
A small part of the code....
 
        case SM_MODBUS_RECEIVE_DATA:
        {
            // See if anyone is connected to us
            if (!TCPIP_TCP_IsConnected(MB_SocketInfo[SKT_Idx].MySocket))
            {
                MB_SocketInfo[SKT_Idx].State = SM_MODBUS_CLOSING_CONNECTION;
                break;
            }
            [.....]
          }
 
        case SM_MODBUS_CLOSING_CONNECTION:
        {
            // Close the socket connection.
            TCPIP_TCP_Close(MB_SocketInfo[SKT_Idx].MySocket);
       
            MB_SocketInfo[SKT_Idx].MySocket = INVALID_SOCKET;
            MB_SocketInfo[SKT_Idx].State = SM_MODBUS_OPENING_SERVER;
            MB_SocketInfo[SKT_Idx].Conn_State = false;
            break;
        }
 
As you can see I use an array to save the socket info and manage a multiple modbus connection.
 
Do you have suggestions on what could be wrong?
 
Thanks
post edited by luca.leoncavallo@gaengineering.com - 2020/03/05 08:15:56
#1
oliverb
Super Member
  • Total Posts : 282
  • Reward points : 0
  • Joined: 2009/02/16 13:12:38
  • Location: 0
  • Status: offline
Re: TCP Socket reuse issue 2020/02/24 09:15:29 (permalink)
5 (1)
Can you tell if the connections closed cleanly? I won't pretend to be an expert but there's a process for closing a session and if a client just silently drops it then unless there's a timeout configured it might not become available again.
#2
NKurzman
A Guy on the Net
  • Total Posts : 18678
  • Reward points : 0
  • Joined: 2008/01/16 19:33:48
  • Location: 0
  • Status: offline
Re: TCP Socket reuse issue 2020/02/24 12:32:11 (permalink)
0
What Version of Harmony?
 
Note the System will use Sockets too.  DHCP, NTP, DNS.
 
I can say Berkeley Sockets work on V1.XX (1.04 to 1.11)
 
#3
RyanF
Starting Member
  • Total Posts : 20
  • Reward points : 0
  • Joined: 2017/04/11 06:31:29
  • Location: 0
  • Status: offline
Re: TCP Socket reuse issue 2020/02/25 05:32:35 (permalink)
5 (1)
Hi
Setting the keep alive time should automatically release a "locked socket" that has no traffic.
I think the default is 10 seconds, you could shorten this (in TCP/IP library block in MHC3)
 
Generally the client should request to close the socket, if no traffic is detected during the keep alive time, the resource is automatically released.
 
i would have expected  TCPIP_TCP_Close to release the resource butt I think it tries to do this "gracefully" ie send FIN messages etc thus taking time. Setting the graceful flag to 0 should immediately release the resource.
 
There are linger and gracefulEnable flags in the TCP_OPTION_LINGER_DATA struct.(tcp.h)
Hopefully this might help
#4
rainad
Moderator
  • Total Posts : 1329
  • Reward points : 0
  • Joined: 2009/05/01 13:39:25
  • Location: 0
  • Status: offline
Re: TCP Socket reuse issue 2020/02/25 13:30:00 (permalink)
0
Another thing to check for is the TCPIP_TCP_MSL_TIMEOUT setting in your project.
If it's != 0 then the socket will be inactive in the  TIME_WAIT/2MSL state after it was closed, so it cannot be re-opened again.
You may change the TCPIP_TCP_MSL_TIMEOUT to 0 (not really recommended by the standards, as it could lead to potential problems) or simply allow more TCP sockets than you use simultaneously.
 
#5
luca.leoncavallo@gaengineering.com
Starting Member
  • Total Posts : 36
  • Reward points : 0
  • Joined: 2015/02/12 03:52:15
  • Location: 0
  • Status: offline
Re: TCP Socket reuse issue 2020/02/27 08:53:17 (permalink)
0
Hi,
 
Sorry but i didn't received the notification for forum messages.
 
FOr the disconnection test I use a standard Modbus client such as "Modbus Poll 5.x" and I simply Connect/Disconnect the modbus.
The harmony i'm using in 2.06
 
It seems that socket remain unavailable forever. If I try also after minutes I still have the problem
#6
RyanF
Starting Member
  • Total Posts : 20
  • Reward points : 0
  • Joined: 2017/04/11 06:31:29
  • Location: 0
  • Status: offline
Re: TCP Socket reuse issue 2020/02/27 09:04:18 (permalink)
0
Hi 
Strange, I have a TCP/IP modbus app that has 4 sockets in an array similar to what you are doing and
do not experience any problems (ie can open close connections from the client side)
If I dont close them cleanly, they all reset after the alive time (10 sec).
 
I use the keep alive time to release any unused/dead sockets.
For testing I use qmodmaster (free on source forge).
 
in system_config.h I have:
 
/*** TCP Configuration ***/
#define TCPIP_TCP_MAX_SEG_SIZE_TX 1460
#define TCPIP_TCP_SOCKET_DEFAULT_TX_SIZE 512
#define TCPIP_TCP_SOCKET_DEFAULT_RX_SIZE 512
#define TCPIP_TCP_DYNAMIC_OPTIONS true
#define TCPIP_TCP_START_TIMEOUT_VAL 1000
#define TCPIP_TCP_DELAYED_ACK_TIMEOUT 100
#define TCPIP_TCP_FIN_WAIT_2_TIMEOUT 5000
#define TCPIP_TCP_KEEP_ALIVE_TIMEOUT 10000
#define TCPIP_TCP_CLOSE_WAIT_TIMEOUT 0
#define TCPIP_TCP_MAX_RETRIES 5
#define TCPIP_TCP_MAX_UNACKED_KEEP_ALIVES 6
#define TCPIP_TCP_MAX_SYN_RETRIES 3
#define TCPIP_TCP_AUTO_TRANSMIT_TIMEOUT_VAL 40
#define TCPIP_TCP_WINDOW_UPDATE_TIMEOUT_VAL 200
#define TCPIP_TCP_MAX_SOCKETS 4
#define TCPIP_TCP_TASK_TICK_RATE 5
#define TCPIP_TCP_MSL_TIMEOUT 0
#define TCPIP_TCP_QUIET_TIME 0
#define TCPIP_TCP_COMMANDS false
#7
luca.leoncavallo@gaengineering.com
Starting Member
  • Total Posts : 36
  • Reward points : 0
  • Joined: 2015/02/12 03:52:15
  • Location: 0
  • Status: offline
Re: TCP Socket reuse issue 2020/02/27 09:06:51 (permalink)
0
Hi Rainad,
 
The parameters TCPIP_TCP_MSL_TIMEOUT is set to 0. I've not changed the TCP settings that i think are the default for Harmony 2.06
 
/*** TCP Configuration ***/
#define TCPIP_TCP_MAX_SEG_SIZE_TX                    1460
#define TCPIP_TCP_SOCKET_DEFAULT_TX_SIZE            512
#define TCPIP_TCP_SOCKET_DEFAULT_RX_SIZE            512
#define TCPIP_TCP_DYNAMIC_OPTIONS                         true
#define TCPIP_TCP_START_TIMEOUT_VAL                    1000
#define TCPIP_TCP_DELAYED_ACK_TIMEOUT                    100
#define TCPIP_TCP_FIN_WAIT_2_TIMEOUT                    5000
#define TCPIP_TCP_KEEP_ALIVE_TIMEOUT                    10000
#define TCPIP_TCP_CLOSE_WAIT_TIMEOUT                    0
#define TCPIP_TCP_MAX_RETRIES                            5
#define TCPIP_TCP_MAX_UNACKED_KEEP_ALIVES            6
#define TCPIP_TCP_MAX_SYN_RETRIES                    3
#define TCPIP_TCP_AUTO_TRANSMIT_TIMEOUT_VAL            40
#define TCPIP_TCP_WINDOW_UPDATE_TIMEOUT_VAL            200
#define TCPIP_TCP_MAX_SOCKETS                        10
#define TCPIP_TCP_TASK_TICK_RATE                    5
#define TCPIP_TCP_MSL_TIMEOUT                        0
#define TCPIP_TCP_QUIET_TIME                        0
#define TCPIP_TCP_COMMANDS   false
#8
rainad
Moderator
  • Total Posts : 1329
  • Reward points : 0
  • Joined: 2009/05/01 13:39:25
  • Location: 0
  • Status: offline
Re: TCP Socket reuse issue 2020/02/27 13:29:26 (permalink)
0
Then let me try to understand exactly what you're doing.
I guess you open a client socket, right:
TCPIP_TCP_ClientOpen(IP_ADDRESS_TYPE_IPV4, remotePort, remoteAddress);
and the remoteAddress is != 0.
Do you get a connection first, the socket communicates OK with the server, before the TCPIP_TCP_IsConnected() fails and you call TCPIP_TCP_Close()?
 
I hope you have a serial console on your system.
If so, please go to the tcpip_private.h file and modify:
#define TCPIP_TCP_DEBUG_LEVEL  3
This will print at the console the socket status.
After that, open the socket normally, communicate with the server and then close it. And let's see where it is stuck.
 
 
 
 
 
post edited by rainad - 2020/02/27 13:30:35
#9
luca.leoncavallo@gaengineering.com
Starting Member
  • Total Posts : 36
  • Reward points : 0
  • Joined: 2015/02/12 03:52:15
  • Location: 0
  • Status: offline
Re: TCP Socket reuse issue 2020/02/28 01:47:16 (permalink)
0
Hi Rainad,
 
I'm sorry. Maybe my bad english make some misunderstanding.
 
The board is a Modbus Server then the init start with
            MB_SocketInfo[SKT_Idx].MySocket = TCPIP_TCP_ServerOpen(IP_ADDRESS_TYPE_IPV4, MODBUS_PORT, 0);
 
The problem is that in the normal operation state of the server, if I disconnect the ModBus client, the call to
 
            if (!TCPIP_TCP_IsConnected(MB_SocketInfo[SKT_Idx].MySocket))
            {
                MB_SocketInfo[SKT_Idx].State = SM_MODBUS_CLOSING_CONNECTION;
                break;
            }
 
Never return false and I never reach the break point placed on the state SM_MODBUS_CLOSING_CONNECTION.
 
Now i'm working to setup a new board for extensive testing.
 
EDIT: I see that when I disconnect the ModBus CLient the smstate changes from TCPIP_TCP_STATE_ESTABLISHED to TCPIP_TCP_STATE_CLOSE_WAIT but nothing more happen. The state remain TCPIP_TCP_STATE_CLOSE_WAIT forever and TCPIP_TCP_IsConnected function return TRUE if the state is TCPIP_TCP_STATE_CLOSE_WAIT.
I have NO idea of the reason for that.
 
 
post edited by luca.leoncavallo@gaengineering.com - 2020/02/28 04:08:21
#10
rainad
Moderator
  • Total Posts : 1329
  • Reward points : 0
  • Joined: 2009/05/01 13:39:25
  • Location: 0
  • Status: offline
Re: TCP Socket reuse issue 2020/02/28 07:32:39 (permalink) ☄ Helpfulby luca.leoncavallo@gaengineering.com 2020/03/05 08:15:10
5 (2)
OK, the fact that you were trying to call TCPIP_TCP_Close() made me think that you're using a client socket.
 
Now the socket being a server socket, the behavior you're describing is the correct and expected one.
The CLOSE_WAIT state simply means that the remote party, the client socket, sent a FIN and closed its side, saying it has nothing more to transmit.
The server socket is still connected (because it can still send data) and will wait for the application to call close when it's done transmitting. This is standard TCP behavior.
 
What you can do:
- use a TCPIP_TCP_CLOSE_WAIT_TIMEOUT value != 0; After this timeout expires, and there's no activity, the socket will close itself. I don't recommend this in a multi-threaded environment, as it could be dangerous.
- you can register a signal handler with the socket, and you'll be notified that the client sent a FIN. Then you can take action. This would be the recommended approach.
- establish some logic in the data stream that tells the server that the client is done and it needs to close its side too
- use keep_alive option on that socket
 
One more point, this being a server socket, when you're done with the connected client, you should call TCPIP_TCP_Disconnect() so the socket is listening again and other clients can connect on that port.
If you call TCPIP_TCP_Close() then the socket will effectively close, so no other connection will be accepted.
 
 
#11
luca.leoncavallo@gaengineering.com
Starting Member
  • Total Posts : 36
  • Reward points : 0
  • Joined: 2015/02/12 03:52:15
  • Location: 0
  • Status: offline
Re: TCP Socket reuse issue 2020/03/05 01:12:17 (permalink)
0
Hi,
 
Finally We solved the problem but I don't know if the solution is acceptable or risky in some ways.
 
Following what I've read in a different forum thread i've changed this:
 
static __inline__ bool __attribute__((always_inline)) _TCP_IsConnected(TCB_STUB* pSkt)
{
    return (pSkt->smState == TCPIP_TCP_STATE_ESTABLISHED || pSkt->smState == TCPIP_TCP_STATE_FIN_WAIT_1 || pSkt->smState == TCPIP_TCP_STATE_FIN_WAIT_2 || pSkt->smState == TCPIP_TCP_STATE_CLOSE_WAIT);
}
 
with this:
 
static __inline__ bool __attribute__((always_inline)) _TCP_IsReallyConnected(TCB_STUB* pSkt)
{
    return (pSkt->smState == TCPIP_TCP_STATE_ESTABLISHED);
}
 
and now, obviously, when the connection changes the state to TCPIP_TCP_STATE_CLOSE_WAIT my state machine goes to SM_MODBUS_CLOSING_CONNECTION and the issue of the re-use of the socket disappear. Now I can connect/disconnect infinite times and works.
 
Luca
#12
rainad
Moderator
  • Total Posts : 1329
  • Reward points : 0
  • Joined: 2009/05/01 13:39:25
  • Location: 0
  • Status: offline
Re: TCP Socket reuse issue 2020/03/05 07:33:29 (permalink)
5 (1)
The change to the TCP_IsConnected() is not correct, as explained above. Plus it affects all TCP sockets, not only the ones you're dealing with now (that is if your application has other TCP connections)..
IMO, messing with the stack to implement a behavior for which there already is a mechanism, is not the right approach.
I'd use a signal handler or the keep alive option, this is how it's supposed to work.
 
 
#13
luca.leoncavallo@gaengineering.com
Starting Member
  • Total Posts : 36
  • Reward points : 0
  • Joined: 2015/02/12 03:52:15
  • Location: 0
  • Status: offline
Re: TCP Socket reuse issue 2020/03/05 08:14:38 (permalink)
0
Hi Rainad,
 
You're right. I miss you previous message but simply setting
 
TCPIP_TCP_CLOSE_WAIT_TIMEOUT 5000
 
solved the problem.
 
Thanks a lot
#14
rainad
Moderator
  • Total Posts : 1329
  • Reward points : 0
  • Joined: 2009/05/01 13:39:25
  • Location: 0
  • Status: offline
Re: TCP Socket reuse issue 2020/03/05 09:37:16 (permalink)
0
You're welcome. Good to hear you got it working as needed now.
 
#15
Jump to:
© 2020 APG vNext Commercial Version 4.5