I have an application which is loosely based off the STM32f4 example which includes +TCP and +CLI. I have a telnet interface which is working pretty well, minus one thing. When I disconnect the Eth cable from the +TCP device, then re-plug, the interface will not connect again, or is unreliable. My question is, what is the best way to deal with cable unplug such that the interface can come back up quickly and reliably after a user reconnects.
Firstly, I would recommend using the following settings:
/* Include support for TCP hang protection. All sockets in a connecting or
disconnecting stage will timeout after a period of non-activity. */
#define ipconfigTCP_HANG_PROTECTION ( 1 )
#define ipconfigTCP_HANG_PROTECTION_TIME ( 30 )
/* Include support for TCP keep-alive messages. */
#define ipconfigTCP_KEEP_ALIVE ( 1 )
#define ipconfigTCP_KEEP_ALIVE_INTERVAL ( 20 ) /* in seconds */
They make sure that dead TCP connections will be cleared.
Are you using a recent STM32Fxx driver?
Is your STM32f4 device a telnet server or a telnet client?
And if it is a server, what value do you give to the parameter xBacklog
when calling FreeRTOS_listen()
? This determines how many telnet session can be opened in parallel.
What telnet client do you use, something like puTTY?
Does your telnet client reconnect “automatically”?
I am using recent version of the STM32Fxx driver. It is actually a stm32f7 device and acting as a server. xBacklog is set to 20, but I am just using a FreeRTOS_accept() and FREERTOS_SO_REUSE_LISTEN_SOCKET option, because for this device I would like to only have 1 connection at a time. I tried to check the FreeRTOS_recv() return value and kill the socket but even when I disconnect the cable I dont get a return value < 0.
If you want to respond quickly to drops in the PHY Link Status, you can poll the status by calling xGetPhyLinkStatus()
. When the answer changes from 1 to 0, you can take action:
Without using the option FREERTOS_SO_REUSE_LISTEN_SOCKET
, all you would do is close the ( connected ) child socket by calling FreeRTOS_closesocket(),
and wait for a new connection in FreeRTOS_accept()
.
When using FREERTOS_SO_REUSE_LISTEN_SOCKET
( i.e. a non-compatible option, made for efficiency ), things are a bit more difficult.
When reusing the socket, the socket you use for listen()
is the same socket ( pointer ) as the connected child socket ( as returned by accept()
). So normally you will never call closesocket()
.
I would recommend to close the socket and create a new one, as soon as the Link Status drops. You can call FreeRTOS_listen()
immediately after creating it, and wait for a new connection.
Note that there is some debouncing in the PHY Status detection. If you want a quick response you can play with this macro:
#define ipconfigPHY_LS_HIGH_CHECK_TIME_MS 15000UL
It will respond after at most 15 seconds. You can bring this down to e.g. 3000 ms.
If it is too short, you may get trouble: frequent polling of the PHY may disturb the transfer of data. You can define it in your FreeRTOSIPConfig.h
.
Background info: normally, if you want to close a socket, you first want to close the TCP connection ( using shutdown()
), and then free the space ( using closesocket()
).
When the Link is down, no communication is possible, so it doesn’t make sense to shutdown()
the TCP connection.
Only when your FreeRTOS device is connected again, the remote telnet client will receive a RST packet, and show an error. That may take a while.
You may wonder why you have to close the socket forcefully when the Link goes down?
Otherwise the IP task will think that the socket is still connected. Only after a time-out it will conclude that the remote party is not responding ( provided that you define ipconfigTCP_KEEP_ALIVE
).
Please report if it works for you. Thanks.
Hi, I’ve a question, when the check report the cable disconnection why the stack doesn’t receive the network down event?
My thinking is that when I get disconnection, the xPlatformIsNetworkUp should return false?