Polling a socket's transfer status ?

6 views
Skip to first unread message

Jean-Christophe

unread,
Dec 8, 2010, 1:34:32 PM12/8/10
to
Hi,

On a non-blocking socket : how can I check if all
data sent by the last call to send() has been
transferred so I can safely shutdown its socket ?

TIA

David Schwartz

unread,
Dec 8, 2010, 7:46:54 PM12/8/10
to

If the protocol you are implementing requires you to confirm that all
data has been sent before permitting you to shut down the socket, then
it must provide some way for you to detect this. For example, the
other side could send some kind of acknowledgment. If it requires this
but provides no way to tell, then the protocol you are implementing on
top of TCP is broken.

In general, however, there is no reason you need to check. Shutting
down the socket is done in an orderly way that includes making sure
all data is sent and acknowledged by the other side.

DS

Jean-Christophe

unread,
Dec 9, 2010, 5:27:11 AM12/9/10
to
On Dec 9, 1:46 am, David Schwartz

| On a non-blocking socket : how can I check if all
| data sent by the last call to send() has been
| transferred so I can safely shutdown its socket ?

I just remember the select() function, but I understand
that a call to select() can't help to tell if all data
has been successfully transferred by send() - am I right ?
( in the case of send() the select() function can only tell
if send() is ready to accept some more data to be sent )

> If the protocol you are implementing requires you to confirm that all
> data has been sent before permitting you to shut down the socket,
> then it must provide some way for you to detect this. For example, the
> other side could send some kind of acknowledgment. If it requires this
> but provides no way to tell, then the protocol you are implementing on
> top of TCP is broken.

Actually I don't implement anything special over TCP, this code
is a subset of a tiny HTTP server, so the other side is a browser.
( the same as my previous post here at alt.winsock.programming )

BTW - I set the socket in non-blocking mode,
so the recv() and send() returns immediately.
Does that explain why calling shutdown() just after
send() is a bad thing to do - what do you think ?

On the server side, I shutdown() the socket just after the call to
send().
It works perfectly on LAN but not on some WAN's browsers. I ran the
WAN
tests with a friend ~ 400 km away, who has a PC on ADSL and a Wi-Fi
LAN.
Sometimes his browser doesn't display at all a page
that has been sent by the server - I traced the send() calls.
( sounds quite strange to me since this is straight HTTP,
it might be my friend's cheap & loosy Wi-Fi connection )
So I added one_second delay between send() and shutdown()
and it worked much better, that's why I guessed that the
shutdown() came too early after the call to the send() function.
Am I right or wrong ?

> In general, however, there is no reason you need to check. Shutting
> down the socket is done in an orderly way that includes making sure
> all data is sent and acknowledged by the other side.

Yes, I think this is the case for HTTP, so what's happening then ?

Yesterday I tried something else : setting the socket as blocking,
and calling select() to check for readability before calling recv().
Since the socket is back to its default blocking mode,
the send() function will only return after full completion
which enables me to call shutdown immedialtely after send().
However I didn't have the chance to test it on WAN yet ...

Thanks for your help Dave.

David Schwartz

unread,
Dec 10, 2010, 10:37:18 AM12/10/10
to
On Dec 9, 2:27 am, Jean-Christophe <5...@free.fr> wrote:

> I just remember the select() function, but I understand
> that a call to select() can't help to tell if all data
> has been successfully transferred by send() - am I right ?
> ( in the case of send() the select() function can only tell
> if send() is ready to accept some more data to be sent )

Right. Even if it could, that would be meaningless to the application.

> > If the protocol you are implementing requires you to confirm that all
> > data has been sent before permitting you to shut down the socket,
> > then it must provide some way for you to detect this. For example, the
> > other side could send some kind of acknowledgment. If it requires this
> > but provides no way to tell, then the protocol you are implementing on
> > top of TCP is broken.

> Actually I don't implement anything special over TCP, this code
> is a subset of a tiny HTTP server, so the other side is a browser.
> ( the same as my previous post here at alt.winsock.programming )

You are implementing HTTP. So follow the HTTP specification for
connection shutdown. Nothing in the HTTP specification every requires
you to know whether data has been sent or not.

> BTW - I set the socket in non-blocking mode,
> so the recv() and send() returns immediately.
> Does that explain why calling shutdown() just after
> send() is a bad thing to do - what do you think ?

If you're done sending and ready to shut down the connection, then you
should certainly call shutdown. Why not? The 'shutdown' function adds
a shutdown to the list of things. TCP requires the implementation to
initiate an orderly shutdown, finish data exchange, and so on.

> On the server side, I shutdown() the socket just after the call to
> send().
> It works perfectly on LAN but not on some WAN's browsers. I ran the
> WAN
> tests with a friend ~ 400 km away, who has a PC on ADSL and a Wi-Fi
> LAN.
> Sometimes his browser doesn't display at all a page
> that has been sent by the server - I traced the send() calls.
> ( sounds quite strange to me since this is straight HTTP,
>   it might be my friend's cheap & loosy Wi-Fi connection )
> So I added one_second delay between send() and shutdown()
> and it worked much better, that's why I guessed that the
> shutdown() came too early after the call to the send() function.
> Am I right or wrong ?

If you didn't change SO_LINGER settings and made sure that the 'send'
succeeded, then it should have worked without the delay. If not,
something is wrong either in your code or in the TCP implementation
you are using.

> > In general, however, there is no reason you need to check. Shutting
> > down the socket is done in an orderly way that includes making sure
> > all data is sent and acknowledged by the other side.

> Yes, I think this is the case for HTTP, so what's happening then ?

Something is wrong either in your code or in the TCP implementations
you are using. Most likely the former.

> Yesterday I tried something else : setting the socket as blocking,
> and calling select() to check for readability before calling recv().
> Since the socket is back to its default blocking mode,
> the send() function will only return after full completion
> which enables me to call shutdown immedialtely after send().
> However I didn't have the chance to test it on WAN yet ...

The 'send' function can still return before still completion. Blocking
just means that it will wait for buffer space, not that it will wait
until it's actually sent.

DS

Jean-Christophe

unread,
Dec 10, 2010, 11:55:00 AM12/10/10
to
On Dec 10, 4:37 pm, David Schwartz

> You are implementing HTTP. So follow the HTTP specification
> for connection shutdown. Nothing in the HTTP specification
> every requires you to know whether data has been sent or not.

Yes, you're perfectly right - I misunderstood.

> If you're done sending and ready to shut down the
> connection, then you should certainly call shutdown.

I agree.

> Why not?

Because the server - MUST - be able to update a browser's page
at any time, which means that the socket must NOT be shut down.

> The 'shutdown' function adds a shutdown to the list of things.
> TCP requires the implementation to initiate an orderly shutdown,
> finish data exchange, and so on.

Yep. The socket is shut down when the user closes its browser,
(or in the event of some fatal SOCKET_ERROR) but not before.

> If you didn't change SO_LINGER settings and made sure that the 'send'
> succeeded, then it should have worked without the delay. If not,
> something is wrong either in your code or in the TCP implementation
> you are using.

Sure. The delay was temporarily added to check things
out, and I threw it. Now everything works just fine.

| Since the socket is back to its default blocking mode,
| the send() function will only return after full completion
| which enables me to call shutdown immedialtely after send().

> The 'send' function can still return before still completion.


> Blocking just means that it will wait for buffer space,
> not that it will wait until it's actually sent.

Yes, now I understand.

Yesterday we ran some tests with my friend. We're
several hundreds km away and have different providers.
For several hours, no problem at all, even with his loosy wi-fi.
And the server is able to update his browser's
page (thru WAN) as well as mine (thru LAN)

Thanks again for your patience on that matter, Dave.

David Schwartz

unread,
Dec 14, 2010, 11:52:06 PM12/14/10
to
On Dec 10, 8:55 am, Jean-Christophe <5...@free.fr> wrote:

> Yesterday we ran some tests with my friend. We're
> several hundreds km away and have different providers.
> For several hours, no problem at all, even with his loosy wi-fi.
> And the server is able to update his browser's
> page (thru WAN) as well as mine (thru LAN)
>
> Thanks again for your patience on that matter, Dave.

You're welcome. Glad you got it sorted out.

The server can never know that the client got the last bit of data
until and unless it times out and closes the socket. That's a
consequence of your forcing a protocol (HTTP) to do something it was
not designed to do. Unfortunately, TCP can't help you. So you have to
live with that little wrinkle.

DS

Reply all
Reply to author
Forward
0 new messages