The issue you are encountering is due to standard behaviour of TCP. When a
client connects to a server, the client specifies a local port number, and the
server's well known port number. These are used along with the IP addresses to
uniquely identify a TCP connection.
When the server end closes the connection first, and the client reacts by
immediately closing its side, the sequence of packets that goes back and forth
is like this:
1. Server sends FIN
2. Client responds with ACK
3. Client sends FIN (can be merged with the previous ACK packet if the client
is fast enough closing its connection)
4. Server responds with ACK
Consider what happens if any of these packets is lost.
1. If the server's FIN is lost, the server will time out on the ACK response
and resend the FIN. The client end doesn't know the connection is closing until
it gets the retried FIN.
2. If the client's ACK is lost, the server will time out on the ACK response
and resend the FIN. The client end discards the repeat FIN as a duplicate and
resends the ACK.
3. If the client's FIN is lost, the client will time out on the ACK response
and resend the FIN. The server end doesn't know that the client has closed its
half of the connection until it gets the retried FIN.
4. If the server's ACK is lost, the client will time out on the ACK response
and resend the FIN. The server end discards the repeat FIN as a duplicate and
resends the ACK.
There is a timeout on this last "TIMED_WAIT" state, typically two minutes.
During this time, the station which closed the connection first (in this case,
the server) is waiting in case the other station missed the final ACK and it
needs to be resent. At the end of that timeout, it is assumed that the client
got the ACK and the server fully closes its connection.
If the server is in this state, and the client tries to establish a new
connection using the same IP address and port number at both ends, then it is
regarded as part of the same connection as the previous one. A connection can't
be reopened while it is established or in the closing states (SYN is only valid
in the opening stages), so the server rejects or ignores the client's
connection attempt.
Some TCP/IP stacks might be clever about this and recognise a new connection
(SYN) with the same port number by cutting short the TIMED_WAIT delay and
immediately closing the old connection. LWIP probably doesn't do that.
The problem can easily be avoided by having the client use a different port
number for opening a new connection. The normal convention for TCP is that the
client allocates a random or incrementing port number in the high range
(49152+) for each new connection. Unless it happens to pick the one which was
used to the same port on the same server within the last two minutes, this
won't be confused with a previous connection in the TIMED_WAIT state.
If the client end closes the connection first, then the server goes straight to
the CLOSED state as soon as it gets the final ACK. In that case, it is the
client which is waiting for two minutes in the TIMED_WAIT state. This will
prevent the client reusing the same port number, because it hasn't been fully
closed yet.
If the server and client close the connection at the same time (their FINs
cross in transit) then they will both be in the TIMED_WAIT state for two
minutes after both ACKs have been sent and received.
The SO_LINGER socket option is typically used to modify the close sequence so
that it will do an "abortive close" by sending a RST instead of FIN. This can
result in loss of data which hasn't been sent or acknowledged yet. It also
doesn't seem to be a complete solution: if the client uses SO_LINGER and sends
RST but the server doesn't receive it, then the client still won't be able to
open a new connection using the same local port number, because the server
won't have fully closed the previous connection. If the server uses SO_LINGER
then the client might miss the RST and not know the connection was closed.
Is there a particular reason that you need to use the same port number for
re-establishing the connection? It is far easier if you just wait two minutes
before reconnecting, or use a different local port number for each connection.
----- Original Message -----
From: Piero 74
To: Mailing list for lwIP users
Sent: Thursday, March 06, 2008 9:31 PM
Subject: Re: [lwip-users] socket: LWIP_ACCEPT problem?
My server application in lwip board, does close operation on socket.
My client exit for "connection closed by peer" and close its socket. I'm
using a run time enviroment to write in easy way windows test application, so,
i cannot set option in socket (i have only basic blocks: listener, connect,
read, write and close)
If i write a server with the same enviroment, and use it with client, the
problem doesn't happen (so: client can reuse the same local port)
I want to know only how lwip manage this situation and why doesn't accept
connection.... i'm trying to understand using debugger, but it's very
difficoult debug a tcp connection!
And if there is a work aorund... i'm thinking to try SO_LINGER option in my
server.... but i don't know if it's correct.
PS: i'm using lwip on embedded system.
Thanks,
Piero
2008/3/5, Bikram Chatterjee <[EMAIL PROTECTED]>:
> I have a simple client on pc running windows.
>
> If the client fixs his local port, accept function accept connection only
the first time, after seems it doesn't accept.
>
> If my client changes its local port for EVERY attempt, accept works
weel!!!
>
> What is the problem???
A TCP connection is uniquely identified by six tuple at any end point
(src_addr, src_port, dst_addr, dst_port). You see that in your case
none of the parameters in the tuple has changed in the second
connection. So the stack has no way of separating packets from this
new connection from that of the previous one.
Are you sure that the second connection actually have originated from
the client? The stack on your client m/c should have stopped it.
Bikram
On Wed, Mar 5, 2008 at 10:12 PM, Bill Auerbach
<[EMAIL PROTECTED]> wrote:
>
> I wrote that because for me the client (Win32) wouldn't reopen the port
if I clicked Close and then Open in my program. Setting SO_LINGER resolved
this. You didn't mention your client, so I guessed (wrong).
>
> How to fix from lwIP? Nothing you've written indicates it is lwIP,
especially if a 3rd party client works.
> ________________________________
>
> From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Piero 74
> Sent: Wednesday, March 05, 2008 10:47 AM
>
> To: Mailing list for lwIP users
> Subject: Re: [lwip-users] socket: LWIP_ACCEPT problem?
>
> Now i'm using a simple client which i wrote....
> By my board will work with a third part client, so, i cannot know if this
pc application will set SO_LINGER.
>
> So, how i can fix the problem from lwip code???
>
> thanks,
> Piero
>
>
> 2008/3/5, Bill Auerbach <[EMAIL PROTECTED]>:
>
> Change the client's SO_LINGER option so it doesn't hang on to the
connection.
>
> Bill
> ________________________________
>
> From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Piero 74
> Sent: Wednesday, March 05, 2008 10:14 AM
> To: Mailing list for lwIP users
> Subject: [lwip-users] socket: LWIP_ACCEPT problem?
>
> Hi all.
>
> I'm testing socket on lwip 130rc1
>
> this is a piece of my code:
>
> // Create a new tcp connection handle
> //----------------------------------------------------------
> sockfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
> serv_addr.sin_family = AF_INET;
> serv_addr.sin_addr.s_addr = INADDR_ANY;
> serv_addr.sin_port = htons(20000);
> bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
> // setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (char*)&bOptVal,
bOptLen);
> listen(sockfd, 0);
> //----------------------------------------------------------
>
> // Loop forever
> while(1)
> {
> // Wait for connection.
> //------------------------------------------------------
> newsockfd = accept(sockfd, &addr, &addrlen);
> bOptVal = TRUE;
> //------------------------------------------------------
> for (i=0; i<10; i++)
> {
> // send 10 hello world!
> lwip_write(newsockfd, provatx, 12);
> }
>
> // close connection
> close(newsockfd);
> }
>
> I have a simple client on pc running windows.
>
> If the client fixs his local port, accept function accept connection only
the first time, after seems it doesn't accept.
>
> If my client changes its local port for EVERY attempt, accept works
weel!!!
>
> What is the problem???
>
> bye,
> Piero
_______________________________________________
lwip-users mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/lwip-users