Socket is stuck in FIN_WAIT (0x18) state.

I have a problem, my HTTP server freezes after a few days of operation. I found that this is due to the fact that the state of the socket is not completely closed (FIN_WAIT (= 0x18)).
I work with W5500 on interrupts, so I can not once again interrogate and see the state of FIN_WAIT, to send comand CLOSED
maybe I skip interruption of disconnection on this so it all happens.

  1. I can not understand why the socket does not go into the CLOSED state?
  2. what external event or internal could trigger such a change?
    There are also some questions about the operation of the TCP server
  3. In the LISTEN state, should a timeout and socket re-open occur?

I guess that your server wants to close the socket after communication is over at its side, sends FIN packet to “properly” disconnect, and never receives FIN/ACK back from the client.

The solution is simple and ugly. You perform DISCON command, wait until it completes, and then perform CLOSE command - and the socket is freed. If remote client will send FIN/ACK back, or will try to talk to the socket, it will get RST packet - this is not a problem because your server is finished with the communicaton and this is in compliance to the TCP proto (if you care about a kind of broken communication process).

Yes, rather you are right, I tested the server through a mobile phone, possibly due to a slow connection, the w5500 did not receive a response signal FIN.

  1. How to determine that a disconnect command has been completed?
    As I wrote, I work through interrupts, and read the register Sn_IR

“Sn_IR (DISCON) Interrupt Thisis issued when FIN or FIN / ACK packet is received from a peer”

I understand w5500 set this flag after the client answers FIN?

Yes.

No, W5500 keep LISTEN state until client is connected.

I suspect so.

After you send last byte to the client, you perform DISCON, wait until Sn_CR register clears (command was accepted) and then immediately perform CLOSE (and again wait for Sn_CR to become 0). And now you can reuse the socket.

For such an event (client not to send the FIN packet) must not be called TIMEOUT?

RTR
During the time configured by RTR, W5500 waits forthe peer response to the packet that is transmitted by Sn_CR(CONNECT, DISCON, CLOSE, SEND, SEND_MAC, SEND_KEEP command). If the peer does not respondwithin the RTR time, W5500 retransmits the packet or issues timeout

I think it must (I do not use interrupts in my implementations), but the depending on timeout set the socket may be hung for relatively long time, thus it is in server’s interests to properly free socket as early as possible (properly = informing client that it has finished by sending FIN packet on DISCON).

Oh, that’s great, since it fits my system well. This happens, rarely enough, so I’m not very scared that the server will free up a bit later, the main thing is that it would free up and not freeze.

The only strange thing is that I have this processing, but for some reason it doesn’t help = ( RTR = 200 and RCR = 3 so that it should be released quickly enough.

How I can this situation be emulated? Can I send SYN,FIN packages manually?

Since there are only 8 sockets available on the W5500, your code will work better if you dispense with some of the formality. I monitor socket statuses and if one is hung in a non-productive state like “FIN” for longer than 250 ms, I force it to close immediately.

First, we need to know why the client does not respond to the FIN packet. The client must send a FIN ACK in response to the FIN. If you do not respond to the FIN at all, the W5500 will timeout the FIN packet. But now no timeout occurs. If the client sends an ACK to the FIN and disconnects, you can use the keepalive function. This function sends a packet periodically. If there is no response from the peer, timeout occurs and the connection is disconnected. You can use the Keep alive function using the Sn_KPALVTR register.

I started to see what was going wrong first caught retransmissions.
192.168.0.114 is wiznet, I fill the entire packet into the socket and give the send command why does it send the packet 2 (3 times) splits it into 3 segments? pack (5,6,7) and why send pack 8 ?

Dump_CGI_GetVar.pcapng.zip (5.2 КБ)
This is a json request dump 3 times

  1. tcp out -of order
  2. norms

Your server (.114) appears to send the response header (HTTP/1.1 200 OK) after the response body (142 bytes). They should be in the opposite order. Afterwards your server starts to close the socket by sending (FIN/ACK). The client (.63) responds to the body or header with an ACK (you may have missed the other ACK that should’ve been there due to slow sampling on your WireShark machine; if so, that’s the likely cause of the ‘out of order’ message.). Then the client sends a (FIN/ACK) to acknowledge the close socket request.

I’d reverse the order in which the response header and body are sent, and don’t close the socket if you want to continue to use it .

1 Like

There seem to be generic logic mistake in how code behaves. Spurious retransmission @24 must not happen, and I am afraid it is W5500 driver instructs to send the data again for some reason.

No, no, everything is correct with the order, the heading is sent first, then the body. I don’t know why Wireshark in the info column displays like this
I open pack header (№5 196 byte):

In this case, wiznet was connected to the computer via cable directly without switches and routers.

Wireshark shows:

  • client sends request for /GetPageVar.CGI
  • server sends ACK
  • server sends header HTTP/1.1 200 OK
  • and immediately performs DISCON
  • and only after DISCON sends the contents of 830 bytes.

You about pack 5-7 ?