Hello :)
I'm developing a ftp client based on the raw API (with callbacks).
It is almost finished and soon will be available for everybody.
I also made a BSD-like sockets API that does not need OS.
I have no real hardware right now, so I'm using the msvc6 port.
I began my work with the cvs from * 2007-11-01.*
There is a stripped version of the function that sends a stream of data
over a socket :
int SendData(struct tcp_pcb *pcb, const void* src, unsigned int
len_arg, unsigned int *progress)
{
err_t err;
u16_t len;
unsigned loop_ack;
/*unsigned*/ int remaining = len_arg;
while (remaining != 0)
{
if (tcp_sndbuf(pcb) < remaining) {// We cannot send more data
than space available in the send buffer.
len = tcp_sndbuf(pcb);
printf("\n sending data in parts of %d bytes\n", len);
}
else {
len = remaining;
printf("\n sending all %d bytes at once,they fit in
tcp_sndbuf==%d :) \n\n", len, tcp_sndbuf(pcb));
}
// try to send len bytes in this loop
do
{
timers_update(); // handle timers (done in tcpip.c when
OS present)
update_adapter(); // check for packets
*tcp_output(pcb); * // prompt the system to send data now
err = tcp_write(pcb, src, len, 0); // to do: if (err !=
ERR_OK) { ... retry?}
tcp_output(pcb);// prompt the system to send data now
timers_update();
update_adapter();
if (err == ERR_MEM) {
len /= 2;
}
printf("\n Bytes ACKed by peer: %d ", pcb->acked); /// !!!!!
} while (err == ERR_MEM && len > 1);
// run timers until peer acknowledges all bytes
loop_ack = LOOPS_ACK_WAIT; // defined as 100 for example
*while (pcb->acked < len)*
{
timers_update();
update_adapter();
printf("\nACKed: %d", pcb->acked);
if(pcb->acked == 0) // this happens when remote
host closes connection
{
// is this indication of a closing connection?
if (((pcb->state) > ESTABLISHED) || ((pcb->state) ==
CLOSED))// waiting to close connection or already close
break;
// no, I have to wait...
if (!loop_ack--){
printf("\n exit by timeout\7\n");
break;
}
}
}
// now len should be == pcb->acked
printf("\n sent (maybe in parts) %d bytes\n\n ", len);
//...
remaining -= len;
// len bytes sent
......
} //while (remaining != 0)
printf("\n everything is now sent ) --> [%s]\n\n", src);
return ERR_OK;
}
Then I made the following test:
{
//... open control connection with server
//... login, open file, open data connection, et..
for (i = 0; i < 100; i++) {
sprintf(databuf, "[%d]", i);
ftp_append(ctrl_s, data_s, databuf, strlen(databuf)); // this
uses int SendData()
}
}
This works fine, peer acknowledges all bytes, the contents of the
uploaded file are as expected:
[0][1][2][3][4][5][6][7][8] ..... [99]
Recently I updated the stack to RC1 and observed quite strange results.
First, the data is corrupted, the file now contains something like
[0][2][2][4][5][5][6][8][9][10][10][11][12][14][16][16][17][17][18][20]....
Some packets are dropped, other are dupplicated
I was trying different situations with putting tcp_output(pcb); and
running the timers
in different places. Sometimes the file contained just parts of a packet:
[0][2]]4]5][5][6]8][9][1...
When I make a simple delay between the packets
(with no calls to timers_update(); and update_adapter();
in the Delay loop)
for (i = 0; i < 100; i++) {
sprintf(databuf, "[%d]", i);
ftp_append(ctrl_s, data_s, databuf, strlen(databuf)); // this
uses int SendData()
Delay(100); // 100 milliseconds
}
things get better
100ms -> results are better
200ms -> almost perfect
>300 ms -> no corruption
I thouht the problem is due to retransmision of packets.
I noticed that the queue gets full, so I inserted another loop that
runs the timers until the queue is
empty again, but this did not solve the problem :(
I think that there may be mistmatch of sequence numbers of
retransmitted packets (maybe they are incremented
when they should not be?)
I dont know why some of the packets are not received at all.
There is also something else which may be the key to the problem:
with RC1 I do not receive ACKs by the server !!!
this line: printf("\n Bytes ACKed by peer: %d ", pcb->acked); /// !!!!!
in the older release showed exactly how many bytes are acknowledged
As you can see, I don't call tcp_output(pcb); before I get
Ack of my "len" bytes.
while (pcb->acked < len)
{
timers_update(); update_adapter();
printf("\nACKed: %d", pcb->acked);
........
if(pcb->acked == 0) // this happens when remote
host closes connection
if (!loop_ack--){
printf("\n exit by timeout\7\n");
break;
}
}
}
I never get ACK and the loop is exited by the timeout.
pcb->acked stays 0 forever and so does pcb->unacked
This retry-loop_ack-times loop worked well before RC1.
there is a part of the debug messages:
sending [[0]
]tcp_write(pcb=00917CE8, data=00129794, len=4, apiflags=0)
tcp_enqueue(pcb=00917CE8, arg=00129794, len=4, flags=0, apiflags=0)
tcp_enqueue: queuelen: 0
tcp_enqueue: queueing 6537:6541 (0x0)
tcp_enqueue: 2 (after enqueued)
tcp_output_segment: rtseq 6537
tcp_output_segment: 6537:6541
Bytes ACKed by peer: 0
SendDataNoPayload():ACKed: 0
exit by timeout
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
sent (maybe partial) 4 byte
===================================================================
sending this:
[[1]
]tcp_write(pcb=00917CE8, data=00129794, len=4, apiflags=0)
tcp_enqueue(pcb=00917CE8, arg=00129794, len=4, flags=0, apiflags=0)
tcp_enqueue: queuelen: 2
tcp_enqueue: queueing 6541:6545 (0x0)
tcp_enqueue: 4 (after enqueued)
Bytes ACKed by peer: 0
SendDataNoPayload():ACKed: 0
exit by timeout
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
sent (maybe partial) 4 bytes
===================================================================
sending throug socket 1, pcb 0x917CE8 ...
sending this:
[[2]
]tcp_write(pcb=00917CE8, data=00129794, len=4, apiflags=0)
tcp_enqueue(pcb=00917CE8, arg=00129794, len=4, flags=0, apiflags=0)
tcp_enqueue: queuelen: 4
tcp_enqueue: queueing 6545:6549 (0x0)
tcp_enqueue: chaining segments, new len 8
tcp_enqueue: 6 (after enqueued)
tcp_receive: queuelen 6 ... 4 (after freeing unacked)
tcp_receive: pcb->rttest 13 rtseq 6537 ackno 6541
tcp_receive: experienced rtt 1 ticks (500 msec).
tcp_receive: RTO 6 (3000 milliseconds)
Data [4] successfully sent over socket 1 CB_active_sent, len = 4
tcp_output_segment: rtseq 6541
tcp_output_segment: 6541:6549
tcp_receive: pcb->rttest 14 rtseq 6541 ackno 6541
.....
Any suggestions?
Regards
Iordan Neshev
Daisy Technology
------------------------------------------------------------------------
_______________________________________________
lwip-users mailing list
address@hidden
http://lists.nongnu.org/mailman/listinfo/lwip-users
------------------------------------------------------------------------
No virus found in this incoming message.
Checked by AVG Free Edition.
Version: 7.5.516 / Virus Database: 269.19.9/1237 - Release Date: 22.01.2008 11:04