|
From: | Ben Bobbitt |
Subject: | [lwip-users] TCP client side problems using netconn api |
Date: | Wed, 15 Apr 2009 00:10:45 -0400 |
Hi all, I’m trying to write a fairly simple HTTP proxy on the
atmel avr32 using 1.3.0 of lwIP Try as I might, I’m unable to find much in the way of
example code for CLIENT side TCP using the netconn api. The behavior I’m seeing is pretty strange. I can
get through 3, sometimes 4 iterations of: netconn_new(TCP) netconn_connect netconn_write netconn_recv (x N segments ) netconn_close netconn_disconnect netconn _delete I’ve had a couple of failure modes. I’ve
made changes to try and resolve the issue, but it seems to only force the
problem deeper. I’m able to send my http request,
receive my responses, etc…. for only a few iterations. Then I experience
one of two failure modes. The first thing I saw
was that start getting ( -3) “connection aborted” error codes
on the netconn_connect() call. This seems to be happening in the tcp stack and the code is
being returned in response to a max syn retries condition. It is
pretty consistent at 3 successes and then failure, never to recover until reset
of the system. I moved some stuff around - and now I get another
pretty consistent failure. I honestly don’t know if the two are
related, other than the seeming coincidence of things working for about 3
iterations before trouble starts. This one appears to be a problem in the tcp
stack with the ack sequence numbers during the disconnect process. I
don’t know much about TCP, but I’ve got wireshark running on the
webserver side and I was able to capture the data and compare the sequence of
events during a successful series vs. the last success prior to failure
city. The sequence of events during a normal sequence is as
follows: Server FIN, ACK seq 433 ack 70 Client
ACK seq
70 ack 434 < - note the ack # is +1 of
the seq prior Client FIN, ACK seq 70 ack 434 Server
ACK seq 434 ack 71 In a connection that isn’t going away properly –
and results in a system that I can’t get usable without a reset: Server FIN, ACK seq 433 ack 70 Client
ACK seq
70 ack 433 < - note the ack # is == seq
prior Client FIN, ACK seq 70 ack 434 Server
ACK seq 434 ack 71 Then I get retransmits from the server of the FIN, ACK
because the client side messed up the ACK to the FIN ACK message. The
client then gets confused by the new FIN, ACK and basically ignores it for a
while, then tries sending his own FIN, ACK…. Anyway, it gets ugly. I’ve got other tasks on the system running TCP server
side and UDP connections, without issues. Am I using the netconn correctly? I am deleting the
netconn after each use, because I was running into similar problems trying to
reuse the same netconn. I think I’ve tried a dozen permutations on this
thing. Also, I am formatting the HTTP requests with the
‘Connection: close’ option, so that the server should be initiating
the close as soon as the response is sent. Any insights or examples of TCP client side operations would
be most appreciated. Here’s the pertinent section of my thread // waits here for a
semaphore to signal a request needs to be sent pxConnection = 0;
while(!pxConnection) // create a netconn for our use {
vTaskDelayUntil( &xLastFocusTime, xDelayLength );
pxConnection = netconn_new(NETCONN_TCP); } err =
netconn_connect(pxConnection,&server_addr,80); if(err != 0) {
free(httpbuffer);
while(netconn_delete(pxConnection) != 0) {
vTaskDelayUntil( &xLastFocusTime, xDelayLength ); }
xSemaphoreGive(IBMsgList.xMutex);
continue; } err =
netconn_write(pxConnection,httpbuffer,strlen(httpbuffer),NETCONN_COPY); if(err != 0) {
free(httpbuffer);
while(netconn_delete(pxConnection) != 0) {
vTaskDelayUntil( &xLastFocusTime, xDelayLength ); }
xSemaphoreGive(IBMsgList.xMutex);
continue; } // wait for the
response from server segcount = 0; offset = 0; while((pxRxBuffer
= netconn_recv(pxConnection)) != 0) {
if(pxRxBuffer < 0) {
free(httpbuffer);
while(netconn_delete(pxConnection) != 0)
{
vTaskDelayUntil( &xLastFocusTime, xDelayLength );
}
continue; }
segcount++; len =
netbuf_len(pxRxBuffer);
if((len + offset) > (MAXHTTPRESPLEN -1))
len = (MAXHTTPRESPLEN - (offset+1));
netbuf_copy(pxRxBuffer,(void*)&httpbuffer[offset],len);
httpbuffer[offset+len] = 0; // make sure it's NULL terminated
offset +=len; } if(offset == 0) { //
connection down
connected = 0;
free(httpbuffer);
netconn_close(pxConnection); while(netconn_delete(pxConnection)
!= 0) {
vTaskDelayUntil( &xLastFocusTime, xDelayLength ); }
netbuf_delete(pxRxBuffer);
pxConnection = 0; // for other modules
xSemaphoreGive(IBMsgList.xMutex);
continue; } err =
netconn_disconnect(pxConnection); err =
netconn_close(pxConnection);
netbuf_delete(pxRxBuffer);
while(netconn_delete(pxConnection) != 0) {
vTaskDelayUntil( &xLastFocusTime, xDelayLength ); } // process the
HTTP response rc =
process_http_response(httpbuffer, offset, hdr); // resets the
semaphore and goes back up and waits to be signaled again Thanks for sticking with me on this rather long post. -Ben |
[Prev in Thread] | Current Thread | [Next in Thread] |