Discussion:
UDP server
(too old to reply)
entropy
2005-10-19 15:45:11 UTC
Permalink
Vital stats:
- Winsock newbie
- XP Pro SP2
- stock IP stack
- MSVC 6.0

Note: This is a blood-simple question, but I'm dealing with a flooded
basement while trying to keep a project on schedule and need help.

I'm having trouble getting a UDP server using recvfrom() to recognize
when the other party has finished sending data. If I use a blocking
socket, then recvfrom() blocks until data comes in (which is OK) but
then blocks again once the client is done transmitting (which is not
OK).

If I use a non-blocking socket, then the CPU is pegged while in the
pre-transmission "if (WSAGetLastError()==WSAEWOULDBLOCK) continue ;"
loop. Once client transmission is complete, I again revert to pre-
transmission behavior (ie, SOCKET_ERROR and WSAEWOULDBLOCK). I at no
time get a simple '0' from recvfrom().

Since I also get SOCKET_ERROR and WSAEWOULDBLOCK during the client
transmission phase, I'm winding up putting Sleep() calls in between
recvfrom() calls, and counting the number of consecutive SOCKET_ERROR
and WSAEWOULDBLOCKs that occur in order to guess when the client has
ended transmission. It's looking so butt-ugly I figure I'm really
heading down the wrong path.

I've tried using select() prior to transmission to stall on the
socket w/o pegging the CPU -- but it doesn't seem to work on non-
connected sockets.

I can supply code if that helps, but one side effect of the problems
in the basement is that my broadband link is running at about 300bps
(ie, about as fast as an acoustic coupler) so I'm trying to get away
with a simple description of the problem first.

Any links to good descriptions of a well-written UDP server,
articles, or discussion would be greatly appreciated. Sorry for the
Winsock newbie status.
entropy
2005-10-19 15:49:11 UTC
Permalink
Post by entropy
- Winsock newbie
- XP Pro SP2
- stock IP stack
- MSVC 6.0
Note: This is a blood-simple question, but I'm dealing with a flooded
basement while trying to keep a project on schedule and need help.
I'm having trouble getting a UDP server using recvfrom() to recognize
when the other party has finished sending data. If I use a blocking
socket, then recvfrom() blocks until data comes in (which is OK) but
then blocks again once the client is done transmitting (which is not
OK).
Clarification on this: The server needs to stop after the client
stops transmitting a spit up some performance stats. It's not a
general-purpose server, but a network performance tool.
Post by entropy
If I use a non-blocking socket, then the CPU is pegged while in the
pre-transmission "if (WSAGetLastError()==WSAEWOULDBLOCK) continue ;"
loop. Once client transmission is complete, I again revert to pre-
transmission behavior (ie, SOCKET_ERROR and WSAEWOULDBLOCK). I at no
time get a simple '0' from recvfrom().
Since I also get SOCKET_ERROR and WSAEWOULDBLOCK during the client
transmission phase, I'm winding up putting Sleep() calls in between
recvfrom() calls, and counting the number of consecutive SOCKET_ERROR
and WSAEWOULDBLOCKs that occur in order to guess when the client has
ended transmission. It's looking so butt-ugly I figure I'm really
heading down the wrong path.
I've tried using select() prior to transmission to stall on the
socket w/o pegging the CPU -- but it doesn't seem to work on non-
connected sockets.
I can supply code if that helps, but one side effect of the problems
in the basement is that my broadband link is running at about 300bps
(ie, about as fast as an acoustic coupler) so I'm trying to get away
with a simple description of the problem first.
Any links to good descriptions of a well-written UDP server,
articles, or discussion would be greatly appreciated. Sorry for the
Winsock newbie status.
--
BUSH: BIG HAT, NO CATTLE.
Arkady Frenkel
2005-10-19 15:58:24 UTC
Permalink
You'll never know that unless you'll use predefined protocol :
( or end marker or length on start ).
Arkady
Post by entropy
- Winsock newbie
- XP Pro SP2
- stock IP stack
- MSVC 6.0
Note: This is a blood-simple question, but I'm dealing with a flooded
basement while trying to keep a project on schedule and need help.
I'm having trouble getting a UDP server using recvfrom() to recognize
when the other party has finished sending data. If I use a blocking
socket, then recvfrom() blocks until data comes in (which is OK) but
then blocks again once the client is done transmitting (which is not
OK).
If I use a non-blocking socket, then the CPU is pegged while in the
pre-transmission "if (WSAGetLastError()==WSAEWOULDBLOCK) continue ;"
loop. Once client transmission is complete, I again revert to pre-
transmission behavior (ie, SOCKET_ERROR and WSAEWOULDBLOCK). I at no
time get a simple '0' from recvfrom().
Since I also get SOCKET_ERROR and WSAEWOULDBLOCK during the client
transmission phase, I'm winding up putting Sleep() calls in between
recvfrom() calls, and counting the number of consecutive SOCKET_ERROR
and WSAEWOULDBLOCKs that occur in order to guess when the client has
ended transmission. It's looking so butt-ugly I figure I'm really
heading down the wrong path.
I've tried using select() prior to transmission to stall on the
socket w/o pegging the CPU -- but it doesn't seem to work on non-
connected sockets.
I can supply code if that helps, but one side effect of the problems
in the basement is that my broadband link is running at about 300bps
(ie, about as fast as an acoustic coupler) so I'm trying to get away
with a simple description of the problem first.
Any links to good descriptions of a well-written UDP server,
articles, or discussion would be greatly appreciated. Sorry for the
Winsock newbie status.
Phil Frisbie, Jr.
2005-10-19 16:17:46 UTC
Permalink
Post by entropy
- Winsock newbie
- XP Pro SP2
- stock IP stack
- MSVC 6.0
Note: This is a blood-simple question, but I'm dealing with a flooded
basement while trying to keep a project on schedule and need help.
I'm having trouble getting a UDP server using recvfrom() to recognize
when the other party has finished sending data. If I use a blocking
socket, then recvfrom() blocks until data comes in (which is OK) but
then blocks again once the client is done transmitting (which is not
OK).
Then add a 'end of transmission' packet to tell the server the transmission is over.
Post by entropy
If I use a non-blocking socket, then the CPU is pegged while in the
pre-transmission "if (WSAGetLastError()==WSAEWOULDBLOCK) continue ;"
loop. Once client transmission is complete, I again revert to pre-
transmission behavior (ie, SOCKET_ERROR and WSAEWOULDBLOCK). I at no
time get a simple '0' from recvfrom().
'0' is a valid length for a UDP message! Only with TCP will you get a
termination notice.
Post by entropy
Since I also get SOCKET_ERROR and WSAEWOULDBLOCK during the client
transmission phase, I'm winding up putting Sleep() calls in between
recvfrom() calls, and counting the number of consecutive SOCKET_ERROR
and WSAEWOULDBLOCKs that occur in order to guess when the client has
ended transmission. It's looking so butt-ugly I figure I'm really
heading down the wrong path.
First, UDP is a connections protocol, so it is up to you to handle a 'session'
or 'connection'. Yes, you can 'connect' a UDP socket to an address, but all that
does is allow you to send() without specifying the address each time, and it
rejects all UDP messages that are not form that address so that you can use
recv() instead of recvfrom().

Second, UDP is not reliable, so you will have lost and possibly even duplicated
messages. It is up to your application to deal with this.
Post by entropy
I've tried using select() prior to transmission to stall on the
socket w/o pegging the CPU -- but it doesn't seem to work on non-
connected sockets.
select() works fine on UDP sockets, so you must have a bug in your code.
Post by entropy
I can supply code if that helps, but one side effect of the problems
in the basement is that my broadband link is running at about 300bps
(ie, about as fast as an acoustic coupler) so I'm trying to get away
with a simple description of the problem first.
Any links to good descriptions of a well-written UDP server,
articles, or discussion would be greatly appreciated. Sorry for the
Winsock newbie status.
--
Phil Frisbie, Jr.
Hawk Software
http://www.hawksoft.com
entropy
2005-10-19 17:22:22 UTC
Permalink
Post by Phil Frisbie, Jr.
Post by entropy
I've tried using select() prior to transmission to stall on the
socket w/o pegging the CPU -- but it doesn't seem to work on non-
connected sockets.
select() works fine on UDP sockets, so you must have a bug in your code.
You're probably right:

{
fd_set rset ;

FD_ZERO( &rset ) ;
FD_SET( sock, &rset ) ;

if ( select( 0,
&rset,
(fd_set *)NULL,
(fd_set *)NULL,
(struct timeval *)NULL ) == SOCKET_ERROR )
{
fprintf( stderr, "select(): failed: %ld\n", WSAGetLastError() ) ;
WSACleanup() ;
exit( -1 ) ;
}
else
if ( cli.debug )
fprintf( stderr, "udp && select(): OK\n" ) ;
}

select() blocks indefinitely, even after transmitting begins. If I
comment this block out, I read data after tranmitting begins, which
I'd think shows that 'sock' is otherwise OK.

MSDN says the first argument to select() is ignored.
Alex Fraser
2005-10-19 19:43:06 UTC
Permalink
[snip]
Post by entropy
Post by Phil Frisbie, Jr.
select() works fine on UDP sockets, so you must have a bug in your code.
{
fd_set rset ;
FD_ZERO( &rset ) ;
FD_SET( sock, &rset ) ;
if ( select( 0,
&rset,
(fd_set *)NULL,
(fd_set *)NULL,
(struct timeval *)NULL ) == SOCKET_ERROR )
{
fprintf( stderr, "select(): failed: %ld\n", WSAGetLastError() ) ;
WSACleanup() ;
exit( -1 ) ;
}
else
if ( cli.debug )
fprintf( stderr, "udp && select(): OK\n" ) ;
}
select() blocks indefinitely, even after transmitting begins. If I
comment this block out, I read data after tranmitting begins, which
I'd think shows that 'sock' is otherwise OK.
There is nothing I can see wrong with the code above. I am unable to explain
the results you describe. Try to construct a minimal but complete example
that exhibits the behaviour.
Post by entropy
MSDN says the first argument to select() is ignored.
On Windows, yes, it is.
Peter Duniho
2005-10-20 00:40:56 UTC
Permalink
Post by Phil Frisbie, Jr.
Then add a 'end of transmission' packet to tell the server the
transmission is over.
Though, with UDP this is not necessarily going to do what is desired. See
below.
Post by Phil Frisbie, Jr.
[...]
First, UDP is a connections protocol
"Connectionless", I believe Phil mean to write.
Post by Phil Frisbie, Jr.
[...]
Second, UDP is not reliable, so you will have lost and possibly even
duplicated messages. It is up to your application to deal with this.
And out of order. Don't forget that UDP datagrams can come out of order.

Which means that any attempt to notify through datagrams that the
transmission is over is fraught with problems. The recipient could receive
that notification multiple times. They might not receive it at all. Or
they could receive the notification before receiving datagrams sent prior to
the notification.

I can imagine ways that these would either not be an issue, or that they
could be fixed. Though, fixing them would be similar to reinventing the
wheel, by adding TCP-like features to one's UDP protocol.

Pete

Alun Jones
2005-10-19 15:57:01 UTC
Permalink
Post by entropy
- Winsock newbie
- XP Pro SP2
- stock IP stack
- MSVC 6.0
Note: This is a blood-simple question, but I'm dealing with a flooded
basement while trying to keep a project on schedule and need help.
I'm having trouble getting a UDP server using recvfrom() to recognize
when the other party has finished sending data. If I use a blocking
socket, then recvfrom() blocks until data comes in (which is OK) but
then blocks again once the client is done transmitting (which is not
OK).
That's what blocking socket operations do - they block until they have
something to return to you.
Post by entropy
If I use a non-blocking socket, then the CPU is pegged while in the
pre-transmission "if (WSAGetLastError()==WSAEWOULDBLOCK) continue ;"
loop. Once client transmission is complete, I again revert to pre-
transmission behavior (ie, SOCKET_ERROR and WSAEWOULDBLOCK). I at no
time get a simple '0' from recvfrom().
Yeah - don't do that. As you've found, continually asking for data on a
non-blocking socket is a waste of CPU time.
Post by entropy
Since I also get SOCKET_ERROR and WSAEWOULDBLOCK during the client
transmission phase, I'm winding up putting Sleep() calls in between
recvfrom() calls, and counting the number of consecutive SOCKET_ERROR
and WSAEWOULDBLOCKs that occur in order to guess when the client has
ended transmission. It's looking so butt-ugly I figure I'm really
heading down the wrong path.
The only way to tell when the client has ended transmission is for the
client to include something in its transmission that tells you when it's
over - either by sending a special character or sequence at the end of its
transmission, or by sending a length value at some point in the
transmission, or (since this is UDP) by ensuring that each transmission is
lodged in its own UDP datagram.
Post by entropy
I've tried using select() prior to transmission to stall on the
socket w/o pegging the CPU -- but it doesn't seem to work on non-
connected sockets.
Here's your problem. Apparently you are using select() wrong, because this
will work. Did you remember to re-fill the fd-set with the list of sockets
you're interested in, each time around the loop? Remember that almost every
time you run select(), it will empty out all the fd-set objects.
Post by entropy
I can supply code if that helps, but one side effect of the problems
in the basement is that my broadband link is running at about 300bps
(ie, about as fast as an acoustic coupler) so I'm trying to get away
with a simple description of the problem first.
Code's always a good thing, especially if you can break it down to a small
sample that proves your point with the minimum of code (that, in itself, is
often a really good debugging exercise, and I've found several problems
while trying to minimise things enough that I could post a sample!)
Post by entropy
Any links to good descriptions of a well-written UDP server,
articles, or discussion would be greatly appreciated. Sorry for the
Winsock newbie status.
The usual Winsock FAQ is at http://www.tangentsoft.net/wskfaq/ - hope it has
something useful for you.

Alun.
~~~~
Loading...