Update... I believe I may have my answer...
The code below is typical of the way I've been doing things... (be kind!)...
This snippet housecleans an array of known client programs...
Code:
// close a client program
VOID TrackerDelRemote(SLOT RemSlot)
{ WCHAR ll[MAX_LOGLINE];
WCHAR hn[MAX_HOSTNAME];
// guard for bad slot
if (Remotes[RemSlot] == NULL)
return;
// kill it
SendDatagram(&Remotes[RemSlot]->Owner,PassCode,
RM_KILLREMOTE,&RemSlot,sizeof(SLOT));
// kludge to allow multitasking
Sleep(100); <---- this is the fix
// log
GetHostName(&Remotes[RemSlot]->Owner,hn);
swprintf(ll,MAX_LOGLINE,L"\"%ls\" on %ls from slot %d",
Programs[Remotes[RemSlot]->PgmSlot]->Remote,hn,RemSlot);
AddToLog(L"Close",ll);
// release memory
free(Remotes[RemSlot]);
Remotes[RemSlot] = NULL; }
And this is the sender...
Code:
// compose and send datagrams
INT SendDatagram(PSOCKADDR To,DWORD PassCode,BYTE Command,PVOID Data,INT DataSize)
{ INT sdgram; // datagram size
FD_SET st; // socket to be tested
TIMEVAL tv; // wait time
INT res;
// set up wait time
st.fd_count = 1;
st.fd_array[0] = hSocket;
tv.tv_sec = 5;
tv.tv_usec = 0;
// insert packet values
*((PDWORD)txDgram + DGRAM_PASS) = PassCode;
*((PBYTE) txDgram + DGRAM_CMD) = Command;
if ((Data != NULL) && (DataSize > 0))
memcpy(txDgram + DGRAM_DATA,Data,DataSize);
sdgram = DataSize + DGRAM_DATA;
// send it
res = sendto(hSocket,txDgram,sdgram,0,To,sizeof(SOCKADDR));
select(1,NULL,&st,NULL,&tv);
return res; }
The answer to why the datagrams were not being sent has to do with the way windows multitasks.
When you launch a message from your program's dispatcher loop, you are working in a single timeslice. The program instance is blocked until all your functions return to the dispatcher loop. Winsock is attached to this instance by it's socket handle.
The first code snippet is launched by a message from the dispatcher, it locates the necessary address data, sends it to the second snippet which composes the datagram and then upon return from creating the datagram, it cleans up the memory from the closed client and finally returns to the windows dispatcher... all without allowing anything else to run... I was inadvertently deleting the address for the datagram before it was sent.
The answer proved simple enough... release the time slice. Note the red marking in the first snippet Sleep(100); Sleep releases the time slice and lets the system multitask... the datagram gets sent. I will probably trim that time down somewhat but for now it's working... and it's only in a couple of spots where there's no back and forth so a short delay is not an issue.
I hate kludges like this but I just don't see any other way to get the job done.
Again thanks to everyone who chipped in to help. It is appreciated.