Best regards
Richard
Andy
Richard Wirth <r.w...@wirthware.da-net.de> wrote in message news:37c31b3a...@news.btx.dtag.de...
>Post a code snippet. Maybe you have a funny race condition or you =
>forgot to reset the event or something.
>
>Andy
>
>Richard Wirth <r.w...@wirthware.da-net.de> wrote in message =
>news:37c31b3a...@news.btx.dtag.de...
>> On an UDP socket only the first WSAEventSelect() with FD_WRITE set
>> leads to an Event in WSAEnumNetworkEvents().
>> All subseqent calls to WSAEventSelect( "FD_WRITE") do not produce a
>> NetworkEvent.
>> It looks like the UDP-Socket never gets ready for writing again after
>> a call to sendto();
>> The identical code (even the binary) was working well on SP3 and fails
>> on SP5.
>> Did they change anything? Or did I something wrong?
>>=20
>> Best regards
>>=20
>> Richard
>
>
Here is a code snippet. It's from a library which also works on unix
platforms and on VxWorks. So many sentences of the original code
are removed and some lines are pseudo code.
(The called functions are appended at the end.)
/* Initialize WINDOWS network ... */
if ((status = WSAStartup(MAKEWORD(2,0), &WSAData)) != 0) {
....
exit (-1);
}
...
SocketList.Add( CreateUdpSocket( 8998));
...
while (1)
{
// First setup all event masks for all active sockets
for( iterator = SocketList.begin();...)
{
DWORD evm = FD_ACCEPT | FD_CONNECT | FD_CLOSE
| ((iterator->MUX_POLLIN)? FD_READ : 0) | ((iterator->MUX_POLLOUT)?
FD_WRITE : 0);
if( WSAEventSelect( iterator->fd, evt_arr[1],
evm))
{
printf( "_server: EventSelect failed
(%d)\n", WSAGetLastError());
return -1;
}
}
.....
// Wait for something
DWORD to;
DWORD rx;
to = Calculate_TimeOut();
rx = WSAWaitForMultipleEvents( NUM_EVTS, evt_arr,
FALSE, to, FALSE);
switch( rx)
{
case WSA_WAIT_EVENT_0+1: // socket transfer
r=1;
break;
case WSA_WAIT_EVENT_0: // pipe event
pipe_hndl();
case WSA_WAIT_TIMEOUT:
r=0;
break;
case WSA_WAIT_FAILED:
default:
r=-1;
}
....
if (r == -1) {
r = WSAGetLastError();
printf ("select failed with error: %d\n", r);
/* poll or select failed -- bad news */
if (__debug > 13) {
printf ("ERROR: _DoServe(): select()
failed\n");
}
return -1;
}
....
if( r == 0)
continue; // restart the outer loop
// socket event ... search the list
for( iterator = SocketList.begin();...)
{
WSANETWORKEVENTS sevt;
ZeroMemory( &sevt, sizeof( sevt));
if( WSAEnumNetworkEvents( iterator->fd, 0,
&sevt))
printf( "_server: EnumEvents failed
%d\n", WSAGetLastError());
else
ev = ((sevt.lNetworkEvents & (FD_READ
| FD_ACCEPT | FD_CONNECT | FD_CLOSE))?MUX_POLLIN:0)
| ((sevt.lNetworkEvents &
FD_WRITE)?MUX_POLLOUT:0);
.....
if (ev) {
/* Normal event, do callout */
(*iterator->pfvHandle) (iterator, ev);
// for udp sockets this calls "udpio_handle()" ( see below)
}
}
} // end while( 1)
////////////////////////////////////////////////////////////////////////////
// here are the elsewhere called functions:
void udpio_handle (struct mux_fd *pMuxFd, int events) {
....
if (events & MUX_POLLOUT) {
....
r = sendto( pMuxFd->fd,
pcData, iSize, 0,
(struct sockaddr *)&saddr, sizeof
(saddr));
}
}
if (events & MUX_POLLIN) {
...
}
}
// create a new UDP Socket
int CreateUdpSocket (int iPort) {
struct sockaddr_in saddr;
int r, len;
int iSock;
iSock = WSASocket (AF_INET, SOCK_DGRAM, 0, NULL, 0,
WSA_FLAG_OVERLAPPED);
if (iSock == -1) {
return -1;
}
saddr.sin_family = AF_INET;
saddr.sin_port = htons ((unsigned short)iPort);
/* Incompatible change, strictly speaking... AK 15Oct96 */
saddr.sin_addr.s_addr = INADDR_ANY;
saddr.sin_zero [0] = 0;
saddr.sin_zero [1] = 0;
saddr.sin_zero [2] = 0;
saddr.sin_zero [3] = 0;
saddr.sin_zero [4] = 0;
saddr.sin_zero [5] = 0;
saddr.sin_zero [6] = 0;
saddr.sin_zero [7] = 0;
r = bind (iSock, (void*)&saddr, sizeof (saddr));
if (r == -1) {
MUX_closesocket (iSock);
return -2;
}
len = sizeof (saddr);
r = getsockname (iSock, (void*)&saddr, &len);
if (iDebugLevel > 4) {
printf ("CreateUdpSocket: Addr=%x, port=%d\n",
(unsigned)ntohl (saddr.sin_addr.s_addr),
(int)ntohs (saddr.sin_port));
}
return iSock;
}
Then, try manual-reset event, and pass TRUE to WSAEnumNetworkEvents.
Andy
It may be the case that something changed, but the current behaviour matches the documentation. Here
is the relevant extract:
The FD_WRITE network event is handled slightly differently. An FD_WRITE network event is recorded
when a socket is first connected with WSPConnect or accepted with WSPAccept, and then after a
WSPSend or WSPSendTo fails with WSAEWOULDBLOCK and buffer space becomes available. Therefore, a
Windows Sockets SPI client can assume that sends are possible starting from the first FD_WRITE
network event setting and lasting until a send returns WSAEWOULDBLOCK. After such a failure the
Windows Sockets SPI client will find out that sends are again possible when an FD_WRITE network
event is recorded and the associated event object is signaled.
Since UDP does not provide any flow control, it is unlikely that a send would ever fail with
WSAEWOULDBLOCK.
Gary
As you say "sendto() on an udp socket will never fail with
WSAEWOULDBLOCK. Thus I think, I never will get a FD_WRITE event on an
udp socket again after connect ( only if the target is konnected via
serial line or so)?
But why is the binary working on SP3? Is this an unknown bug in SP3?
But thanks to all!
I think this way, the code is working well now.
Best regards
Richard