| The problem is with overlapped IO and is new for Winsock 2. You call WSASend( ... , lpCompletionRoutine) . The
operation is initiated and the application gets a callback when complete.
I have seen this problem myself. An application that runs fine fails in the debugger. It can be caused by a
couple of problems:
1) not using a unique WSAOVERLAPPED structure (initialized to zero) for EACH overlapped call.
2) bugs in the DECnet SPI pws2dnet.wsp.
I have fixed the bugs in pws2dnet.wsp and this fix will be available in PATHWORKS 32 v 7.0A . I have included a
programming example below. If the customer's problem is urgent, mail me and I will try to troubleshoot it.
Ken Robinson
PATHOWRKS 32
WinSock 2 DECnet
[email protected]
// Overlapped IO
// There are two methods of using overlapped IO with Winsock2 described below:
// 1) Callback functions
// you must declare an overlapped completion routine that will be called when the overlapped operation is
done
void __declspec(dllexport) CALLBACK CompRoutine(DWORD dwError, DWORD cbTransferred,
LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags)
{
printf("completion dwError: %d, cbTransferred: %d, dwFlags: %d\n", dwError, cbTransferred,
dwFlags);
}
// You need a different overlapped structure for each overlapped send or receive.
// Do not modify any field in the WSAOVERLAPPED structure.
WSAOVERLAPPED overlap;
// You must create an overlapped socket
socknew = WSASocket(AF_DECnet, SOCK_STREAM, DNPROTO_NSP, 0, 0, WSA_FLAG_OVERLAPPED);
// Then call WSASend or WSARecv
rc = WSASend(socknew, lpwsabufsend, buffercount, lpbytessent, 0, &overlap, &CompRoutine);
if (rc != 0) {
rc = WSAGetLastError();
if (rc == WSA_IO_PENDING) {
// the overlapped operation is pending
// lpbytessent is not updated
// this thread needs to be in an alertable wait state to allow the completion routine to
be called
// SleepEx() or WSAWaitForMultipleEvents() with fAlertable set to TRUE will work
SleepEx(INFINITE, TRUE);
// the completion routine will be called and this thread will wake up
} else {
// handle error
}
}else {
// send completed immediately
// lpbytessent will be updated
// the completion routine will not be called
}
// 2) Event Objects
// You need a different overlapped structure for each overlapped send or receive.
WSAOVERLAPPED overlap;
// You need a unique event object for each overlapped structure.
// This is the only field you should modify in the WSAOVERLAPPED structure. And you should only modify it
when you
// create or close an event object.
overlap.hEvent = WSACreateEvent();
// You must create an overlapped socket
socknew = WSASocket(AF_DECnet, SOCK_STREAM, DNPROTO_NSP, 0, 0, WSA_FLAG_OVERLAPPED);
// Then call WSASend or WSARecv
rc = WSARecv(socknew, lpwsabufrecv, buffercount, lpbytesrcvd, 0, &overlap,0);
if (rc != 0) {
rc = WSAGetLastError();
if (rc == WSA_IO_PENDING) {
// the overlapped operation is pending
// lpbytesrcvd is not updated
} else {
// handle error
}
}else {
// recv completed immediately
// lpbytesrcvd will be updated
// the completion routine will not be called
}
// Now you need to get the results of the overlapped receive. You can have multiple overlapped operations
pending on a
// socket, so the WSAOVERLAPPED structure is used to retreive the results of a particular operation.
// There are three possible ways to do this:
// 1: Call WSAGetOverlappedResult with fWait set to TRUE. This blocks until the overlapped operation is
done
rc = WSAGetOverlappedResult(socknew, &overlap, lpbytesrcvd2, TRUE, lpflags);
// 2: Call WSAWaitForMultipleEvents() and then WSAWSAGetOverlappedResult with fWait set to FALSE.
// This method can be used to wait until more than one overlapped operation is done.
rc = WSAWaitForMultipleEvents(1, &overlap.hEvent, TRUE, WSA_INFINITE, FALSE);
// This blocks until the overlapped operation is done
rc = WSAGetOverlappedResult(socknew, &overlap, lpbytesrcvd2, FALSE, lpflags);
// 3: Poll by calling WSAGetOverlappedResult() repeatedly with fWait set to FALSE.
do {
rc = WSAGetOverlappedResult(socknew, &overlap, lpbytesrcvd2, FALSE, lpflags);
} while (rc == FALSE);
// make sure you close the event object when you are done with it
WSACloseEvent(overlap.hEvent);
overlap.hEvent = WSA_INVALID_EVENT;
// end
|