Discussion:
CSocket, DLL and OnReceive never being called
(too old to reply)
sc
2006-03-21 18:01:00 UTC
Permalink
'Allo!

I am writing a regular DLL (using shared MFC) that works with CSockets.
This DLL is loaded by a service that has no message pump.

I created a UI thread (derived from CWinThread) and all socket-related
work is done from here. I can connect to the server, send messages,
etc. The problem is that OnReceive is never called on my socket.

Does anyone have an idea what might be the problem?

Thanks in advance!
Sandra
Michael K. O'Neill
2006-03-22 01:59:23 UTC
Permalink
Post by sc
'Allo!
I am writing a regular DLL (using shared MFC) that works with CSockets.
This DLL is loaded by a service that has no message pump.
I created a UI thread (derived from CWinThread) and all socket-related
work is done from here. I can connect to the server, send messages,
etc. The problem is that OnReceive is never called on my socket.
Does anyone have an idea what might be the problem?
Thanks in advance!
Sandra
I'm not certain, but CSocket would not ever call OnReceive since CSocket is
intended to mimic a blocking, synchronous socket.

Try CAsyncSocket instead.
sc
2006-03-22 02:53:26 UTC
Permalink
I have to use the same library deployed by other 'clients', and in this
case that's the CSocket-derived class I'm having issues with. The other
'client' is an MFC app, and has no problems with messages and stuff. I
checked, and 'OnReceive' does get called for that case (for CSocket,
that is). Here is the top of the call stack:


CMySocket::OnReceive(int 0) line 41
CAsyncSocket::DoCallBack(unsigned int 1880, long 1) line 530
CSocket::ProcessAuxQueue() line 823
CSocketWnd::OnSocketNotify(unsigned int 1880, long 1) line 1127
CWnd::OnWndMsg(unsigned int 883, unsigned int 1880, long 1, long *
0x0012f55c) line 1826 + 17 bytes
CWnd::WindowProc(unsigned int 883, unsigned int 1880, long 1) line 1596
+ 30 bytes
AfxCallWndProc(CWnd * 0x00328b18 {CSocketWnd hWnd=0x000205b4}, HWND__ *
0x000205b4, unsigned int 883, unsigned int 1880, long 1) line 215 + 26
bytes
AfxWndProc(HWND__ * 0x000205b4, unsigned int 883, unsigned int 1880,
long 1) line 379
AfxWndProcBase(HWND__ * 0x000205b4, unsigned int 883, unsigned int
1880, long 1) line 220 + 21 bytes
USER32! 77d48734()
USER32! 77d48816()
USER32! 77d489cd()
USER32! 77d496c7()
CWinThread::PumpMessage() line 853
CWnd::RunModalLoop(unsigned long 4) line 3489 + 19 bytes
......


I'm mucking around with messages, they do not seem to get to the dll,
despite my UI thread (the only 'solution' to the issue I've found so
far).
Scott McPhillips [MVP]
2006-03-22 03:42:36 UTC
Permalink
Post by Michael K. O'Neill
Post by sc
'Allo!
I am writing a regular DLL (using shared MFC) that works with CSockets.
This DLL is loaded by a service that has no message pump.
I created a UI thread (derived from CWinThread) and all socket-related
work is done from here. I can connect to the server, send messages,
etc. The problem is that OnReceive is never called on my socket.
Does anyone have an idea what might be the problem?
Thanks in advance!
Sandra
I'm not certain, but CSocket would not ever call OnReceive since CSocket is
intended to mimic a blocking, synchronous socket.
Try CAsyncSocket instead.
CSocket should call OnReceive. Make sure that you are calling
AfxSocketInit from your UI thread. Make sure that your code returns to
the CWinThread message pump. The only reason for OnReceive failing that
I can think of is that you might be blocking or looping in your code
instead of returning to CWinThread::Run so it can dispatch messages.
--
Scott McPhillips [VC++ MVP]
sc
2006-03-22 04:29:23 UTC
Permalink
Nope, that's not the case. I already verified taht CWinThread::Run is
functioning properly. CWinThread::Pump message is being called
(confirmed through debugging and logging), with OnIdle returning 0.

AfxSocketInit was already there. The client does connect to the server,
and sends messages that server receives. But, when the server sends
something back, my socked doesn't get it. This is sooo frustrating!!!

Thanks for the time!!
Ed Weir (ComCast)
2006-03-22 06:45:18 UTC
Permalink
"sc" <a_quarius3-***@yahoo.ca> wrote in message news:***@j33g2000cwa.googlegroups.com...
| Nope, that's not the case. I already verified taht CWinThread::Run is
| functioning properly. CWinThread::Pump message is being called
| (confirmed through debugging and logging), with OnIdle returning 0.
|
| AfxSocketInit was already there. The client does connect to the server,
| and sends messages that server receives. But, when the server sends
| something back, my socked doesn't get it. This is sooo frustrating!!!
|
| Thanks for the time!!
|

I've seen this problem, and have devised a workaround for it. It seems as
if the last send from your side is lost or ignored, and/or then the other
end simply stops sending data.

I posted my working solution here in a previous message; if you can't find
it let me know. I'll dig it up and resend it for you.

- Ed.
sc
2006-03-22 06:52:26 UTC
Permalink
What gets lost when? I follow the message sent by the client to the
server (received by the server), and the server sends a message back
(not received by the client).

I tried to find a relevant post you mentioned - I'd appreciate if you
could re-send it, or let me know when it was written.

Thanks !!
Ed Weir (ComCast)
2006-03-22 07:13:00 UTC
Permalink
"sc" <a_quarius3-***@yahoo.ca> wrote in message news:***@i40g2000cwc.googlegroups.com...
| What gets lost when? I follow the message sent by the client to the
| server (received by the server), and the server sends a message back
| (not received by the client).
|
| I tried to find a relevant post you mentioned - I'd appreciate if you
| could re-send it, or let me know when it was written.
|
| Thanks !!
|

[clipped from archive...]


"Bill Brehm >" <<don't want any spam> wrote in message news:***@TK2MSFTNGP12.phx.gbl...
| Thanks everyone. I have it working pretty well now.
|
| "Scott McPhillips [MVP]" <org-dot-mvps-at-scottmcp> wrote in message
| news:***@TK2MSFTNGP12.phx.gbl...
| > Scott McPhillips [MVP] wrote:
| >> Shutdown is a blocking call.
| >
| > My "gracefull close" wrapper, based on the defensive design
| > recommendations of Quinn & Shute in "Windows Sockets Network
Programming"
| >
| > int nbytes;
| > BYTE buf[4096];
| > ShutDown(1); // SD_SEND
| > do {
| > nbytes = CAsyncSocket::Receive(buf, 4096);
| > } while (nbytes != SOCKET_ERROR && nbytes > 0);
| > CAsyncSocket::Close();
| >
| > --
| > Scott McPhillips [VC++ MVP]
| >
|

Uh oh... the code snippet you submitted above will expose you to an infinite
hang condition if the socket fails to receive data. You should always 'look
ahead' to see if data is available before calling Receive(): For example,

DWORD dwStartTick = GetTickCount(), dwBytes = 0;
while(0 == dwBytes)
{
// Look ahead via IOCtl
if(!IOCtl(FIONREAD, &dwBytes))
{
TRACE("IOCtl FIONREAD Failed");
return; // Fatal
}

if(dwBytes)
break;

Sleep(25);
if(GetTickCount() - dwStartTick > HOST_TIMEOUT)
{
TRACE("TIMEOUT");
return;
}
}

Now it is safe to call Receive(). It is always unwise to call a blocking
Receive() without knowing there is something to receive or not. Adding a
Sleep() call and a timeout value further improves product stability and
prevents CPU overloading while awaiting data.

- Ed.
=========================================================================
P.S., Although Receive() is advertised as a non-blocking call, tracing it
through to its base class reveals that it does actually call recv() without
verifying that data exists yet, resulting in a condition where messages are
being pumped, but no response gets received from the other end. In later
versions of the MFC libraries this might have been fixed, but in the VC 6
libs it is not.
sc
2006-03-22 13:37:15 UTC
Permalink
Unfortunately, the CSocket-derived class I'm working with is using
CFile and CArchive, Read is not used for OnReceive.
sc
2006-03-22 13:39:27 UTC
Permalink
Besides, even if Receive was used inside OnReceive, the problem here is
that I NEVER GET into OnReceive. The pump in UI thread never gets the
message, and therefore never can dispatch it to the socket....
Ed Weir (ComCast)
2006-03-22 19:43:00 UTC
Permalink
"sc" <a_quarius3-***@yahoo.ca> wrote in message news:***@t31g2000cwb.googlegroups.com...
| Besides, even if Receive was used inside OnReceive, the problem here is
| that I NEVER GET into OnReceive. The pump in UI thread never gets the
| message, and therefore never can dispatch it to the socket....
|

Then the best advice I have for you is the same I give everyone who works
for me:
"If it doesn't work like it's supposed to, FIX IT!"

Seriously... Windows messages sometimes 'get lost'; that is, for some
unknown reason the expected message is either not posted or is lost in the
queue after posting; the result is the same, you don't get it. You'll have
to remodel your code a little to get the data from the device buffer. I
gave you the code to do that. That might mean that you'll have to call
OnReceive() manually in your code, and take a step to prevent unwanted
recursion if the message hits after you have called OnReceive().

These are just suggestions, I not knowing your code or architecture or
anything. I am pretty certain that, given the case you described, the data
is waiting for you to get via Receive().

-Ed.
sc
2006-03-22 23:01:30 UTC
Permalink
I wish I could persuade you that it's not waiting to be received. :) I
have a breakpoint in the message pump of the app that's using the
socket, and the darn thing just doesn't seem to get it. This is a royal
pain in the butt.

After much mucking around, I decided to switch to CAsyncSocket.
Adjusting to the data format that the servers expects will be messy,
but at least I got the messages flowing between the two.

Thanks for the help!!
Ed Weir (ComCast)
2006-03-22 23:51:09 UTC
Permalink
??????????
"sc" <a_quarius3-***@yahoo.ca> wrote in message news:***@e56g2000cwe.googlegroups.com...
|I wish I could persuade you that it's not waiting to be received. :) I
| have a breakpoint in the message pump of the app that's using the
| socket, and the darn thing just doesn't seem to get it. This is a royal
| pain in the butt.
|
| After much mucking around, I decided to switch to CAsyncSocket.
| Adjusting to the data format that the servers expects will be messy,
| but at least I got the messages flowing between the two.
|
| Thanks for the help!!
|

How does switching class derivations affect data format?? I think someone
mentioned you should be using CAsyncSocket anyways.

Glad you solved the problem!
- Ed.
sc
2006-03-23 00:36:23 UTC
Permalink
I suppose I wasn't clear enough. The whole issue happened because I
wanted to use some existing libraries written for that purpose - to be
used by client applications. The libraries contain all the code needed
to handle formatting data sent between clients and the sever (among
other things, CAsyncSocket cannot use CArchive and such, which the
mentioned libraries use a lot).

Re-writing a lot of client code 'just because it doesn't work this way'
is not always the best solution. You would be expected to have a
reasonable explanation to start re-inventing the wheel (as it might
look to the management).

Since it seems that figuring out how to make use of existing
CSocket-related code would take way too long, I'll just rewrite the
whole thing with CAsyncSocket. That's the 'messy' part I was talking
about.
sc
2006-03-31 22:58:45 UTC
Permalink
I ended up having to switch to WinSock. Man, did I ever run into a lot
of ***@p with MFC sockets, and none of the many suggested solutions
worked for me. WinSock it is!

Thanks everyone!

Loading...