Discussion:
[lwip-users] question about netconn_write
yueyue papa
2008-12-13 12:20:52 UTC
Permalink
Hi All,

I am using lwIP 1.3+ PPP working in GPRS environment.
I meet following case

There is TCP connection between A,B.
A: B:
------------- -->
<---------------
------------- -->
<--------------- ------------- -->
<---------------

Some time the flow could work correct, some time A is waiting, and B is
waiting. I put in the LAN environment, every thing is ok. The problem is
only in GPRS environment. Anther side in out of my control I unable to run
wireshark to monitor what happened.

After I read the code, I have this guess. May this thing possible that
netconn_write return, but the data is not send out.

netconn_write return means

1> Data in the TCP/IP stack

Wether it comes out depend the task schedule, if the data is lost in the
line, the netconn_write already returned.

If it is true, is the any API could i flush the data in the send buffer,
force the data send out, and make sure the data has been ACK by remote.

Lee
Kieran Mansley
2008-12-13 13:11:24 UTC
Permalink
Post by yueyue papa
Wether it comes out depend the task schedule, if the data is lost in
the line, the netconn_write already returned.
Yes, but if it gets lost, TCP should retransmit it. If you're using
UDP, and expecting all the data to get through, then that's a problem.
None of the lwIP APIs have a "send" function that waits until the data
has successfully crossed the network.
Post by yueyue papa
If it is true, is the any API could i flush the data in the send
buffer, force
the data send out, and make sure the data has been ACK by remote.
If you do something like this:
netconn.pcb.tcp->flags |= TF_NODELAY;

then you will disable Nagle's algorithm, which is the most common reason
that writes are delayed and batched together for sending. Note that
this might result in small transmissions which are inefficient if you're
about to queue some more data anyway.

However, it sounds like you were hoping that netconn_write() wouldn't
return until the data had been successfully received and acknowledged by
the other side. That still won't be the case if you set TF_NODELAY.

If you were using the raw API you can call tcp_write() to queue the data
and tcp_output() to send it at times that are sensible for your
application.

Kieran
yueyue papa
2008-12-13 13:59:53 UTC
Permalink
Thanks

Based on your suggtion,

I tried to add a lwip_tcpflush(int s)

int lwip_tcpflush(int s)
{
struct lwip_socket *sock;
sock = get_socket(s);
if (!sock)
return -1;
return tcp_output(sock->conn.pcb.tcp);
}

Will it force data flush ?

I will make test.
Thank you very much
Post by Kieran Mansley
Post by yueyue papa
Wether it comes out depend the task schedule, if the data is lost in
the line, the netconn_write already returned.
Yes, but if it gets lost, TCP should retransmit it. If you're using
UDP, and expecting all the data to get through, then that's a problem.
None of the lwIP APIs have a "send" function that waits until the data
has successfully crossed the network.
Post by yueyue papa
If it is true, is the any API could i flush the data in the send
buffer, force
the data send out, and make sure the data has been ACK by remote.
netconn.pcb.tcp->flags |= TF_NODELAY;
then you will disable Nagle's algorithm, which is the most common reason
that writes are delayed and batched together for sending. Note that
this might result in small transmissions which are inefficient if you're
about to queue some more data anyway.
However, it sounds like you were hoping that netconn_write() wouldn't
return until the data had been successfully received and acknowledged by
the other side. That still won't be the case if you set TF_NODELAY.
If you were using the raw API you can call tcp_write() to queue the data
and tcp_output() to send it at times that are sensible for your
application.
Kieran
_______________________________________________
lwip-users mailing list
http://lists.nongnu.org/mailman/listinfo/lwip-users
Kieran Mansley
2008-12-13 14:15:24 UTC
Permalink
Post by yueyue papa
Thanks
Based on your suggtion,
I tried to add a lwip_tcpflush(int s)
int lwip_tcpflush(int s)
{
struct lwip_socket *sock;
sock = get_socket(s);
if (!sock)
return -1;
return tcp_output(sock->conn.pcb.tcp);
}
Will it force data flush ?
Yes, but you've completely broken the threading protection: the sockets
code can't access the internal functions of lwIP directly, they must use
a message to invoke an action in the tcpip thread.

Kieran
yueyue papa
2008-12-13 14:36:27 UTC
Permalink
so elegement solution will be add a new kind of message type ,and let
tcpip_thread to process.
Post by Kieran Mansley
Post by yueyue papa
Thanks
Based on your suggtion,
I tried to add a lwip_tcpflush(int s)
int lwip_tcpflush(int s)
{
struct lwip_socket *sock;
sock = get_socket(s);
if (!sock)
return -1;
return tcp_output(sock->conn.pcb.tcp);
}
Will it force data flush ?
Yes, but you've completely broken the threading protection: the sockets
code can't access the internal functions of lwIP directly, they must use
a message to invoke an action in the tcpip thread.
Kieran
_______________________________________________
lwip-users mailing list
http://lists.nongnu.org/mailman/listinfo/lwip-users
yueyue papa
2008-12-13 14:40:12 UTC
Permalink
Thanks Kieran again.

i really do not known the rule you refered. ( You are correct.)

i am very like lwIP support flush in socket level. i could write the code,
hope lwIP could add it in its standard solution.
Post by yueyue papa
so elegement solution will be add a new kind of message type ,and let
tcpip_thread to process.
Post by Kieran Mansley
Post by yueyue papa
Thanks
Based on your suggtion,
I tried to add a lwip_tcpflush(int s)
int lwip_tcpflush(int s)
{
struct lwip_socket *sock;
sock = get_socket(s);
if (!sock)
return -1;
return tcp_output(sock->conn.pcb.tcp);
}
Will it force data flush ?
Yes, but you've completely broken the threading protection: the sockets
code can't access the internal functions of lwIP directly, they must use
a message to invoke an action in the tcpip thread.
Kieran
_______________________________________________
lwip-users mailing list
http://lists.nongnu.org/mailman/listinfo/lwip-users
yueyue papa
2008-12-14 14:14:29 UTC
Permalink
I use TCP_NODELAY, the problem solved.

I suggest lwIP provide a suggestion to implement flush feature. So do not
use TCP_NODELAY for all environement, and let application use flush in its
application
Post by yueyue papa
Thanks Kieran again.
i really do not known the rule you refered. ( You are correct.)
i am very like lwIP support flush in socket level. i could write the code,
hope lwIP could add it in its standard solution.
Post by yueyue papa
so elegement solution will be add a new kind of message type ,and let
tcpip_thread to process.
Post by Kieran Mansley
Post by yueyue papa
Thanks
Based on your suggtion,
I tried to add a lwip_tcpflush(int s)
int lwip_tcpflush(int s)
{
struct lwip_socket *sock;
sock = get_socket(s);
if (!sock)
return -1;
return tcp_output(sock->conn.pcb.tcp);
}
Will it force data flush ?
Yes, but you've completely broken the threading protection: the sockets
code can't access the internal functions of lwIP directly, they must use
a message to invoke an action in the tcpip thread.
Kieran
_______________________________________________
lwip-users mailing list
http://lists.nongnu.org/mailman/listinfo/lwip-users
Loading...