Discussion:
CSocket OnReceive Problem
(too old to reply)
Sakthi
2005-02-04 19:23:04 UTC
Permalink
Hai,

I am having problem with OnReceive notification of my own class derived
from CSocket. I created a thread, and attaches many client sockets to the
thread (accepting clients in another thread, and posting a message to this
thread to attach). Now, my OnReceive notification, has not always called.
Some times, it is called, and some times, I dont know, why it is not called.
Can anybody answer?
James Simpson
2005-02-06 11:47:02 UTC
Permalink
Hello,
The problem is likely due to threading. If you share one thread with say 10
active connections and lets say that 2 messages are received at around the
same time (give or take a few milliseconds), since a computer can only do one
thing at a time it will receive the first incoming message but not the second
one, the second message will just be a lost message (in other words the
message would never be received). To solve this problem, create a worker
thread to handle either each socket connection that was created, or find a
way to 'cache' the data that comes into the software. MFC's networking and
threading isn't that great (let that be a fair warning). I might suggest in
this case looking at .NET, because I have heard that .NET is supposed to
solve some of these issues with multithreading and socketing.

Sincerely,
James Simpson
Scott McPhillips [MVP]
2005-02-06 14:12:37 UTC
Permalink
Post by James Simpson
Hello,
The problem is likely due to threading. If you share one thread with say 10
active connections and lets say that 2 messages are received at around the
same time (give or take a few milliseconds), since a computer can only do one
thing at a time it will receive the first incoming message but not the second
one, the second message will just be a lost message (in other words the
message would never be received). To solve this problem, create a worker
thread to handle either each socket connection that was created, or find a
way to 'cache' the data that comes into the software. MFC's networking and
threading isn't that great (let that be a fair warning). I might suggest in
this case looking at .NET, because I have heard that .NET is supposed to
solve some of these issues with multithreading and socketing.
Sincerely,
James Simpson
A coule of corrections to your theory, James:

The socket does not lose data. It holds it in a buffer until the
application calls Receive. If the application does not call then the
TCP/IP handshake with the source assures that the buffer will not overrun.

CSocket and CAsyncSocket will not work in a worker thread, because they
generate OnReceive/OnSend using the MFC message pump, which is not
present in a worker thread. They require the so-called "user interface"
type of MFC thread.

To the original poster: Try calling Receive one time only in each
OnReceive, and make sure your OnReceive processing does not call
anything that pumps messages (such as MessageBox). If that does not fix
the problem then it is highly recommended you use CAsyncSocket instead
of CSocket. CSocket is an awkward, terrible, unreliable design.
--
Scott McPhillips [VC++ MVP]
Sakthi
2005-02-06 14:47:03 UTC
Permalink
Thanks James for taking time to reply me.

Very kind of u Scott. I tried to use only one receive() inside OnReceive().
Now, it is working fine. Also, advanced thanx to u for going to solving my
problem "WaitForSingleObject( ) debug - release version" which i have posted
today.
Post by Scott McPhillips [MVP]
Post by James Simpson
Hello,
The problem is likely due to threading. If you share one thread with say 10
active connections and lets say that 2 messages are received at around the
same time (give or take a few milliseconds), since a computer can only do one
thing at a time it will receive the first incoming message but not the second
one, the second message will just be a lost message (in other words the
message would never be received). To solve this problem, create a worker
thread to handle either each socket connection that was created, or find a
way to 'cache' the data that comes into the software. MFC's networking and
threading isn't that great (let that be a fair warning). I might suggest in
this case looking at .NET, because I have heard that .NET is supposed to
solve some of these issues with multithreading and socketing.
Sincerely,
James Simpson
The socket does not lose data. It holds it in a buffer until the
application calls Receive. If the application does not call then the
TCP/IP handshake with the source assures that the buffer will not overrun.
CSocket and CAsyncSocket will not work in a worker thread, because they
generate OnReceive/OnSend using the MFC message pump, which is not
present in a worker thread. They require the so-called "user interface"
type of MFC thread.
To the original poster: Try calling Receive one time only in each
OnReceive, and make sure your OnReceive processing does not call
anything that pumps messages (such as MessageBox). If that does not fix
the problem then it is highly recommended you use CAsyncSocket instead
of CSocket. CSocket is an awkward, terrible, unreliable design.
--
Scott McPhillips [VC++ MVP]
jaky
2011-06-21 09:41:30 UTC
Permalink
Sakthi wrote on 02/06/2005 09:47 ET
Post by Sakthi
Thanks James for taking time to reply me
Very kind of u Scott. I tried to use only one receive() inside OnReceive()
Now, it is working fine. Also, advanced thanx to u for going to solving m
problem "WaitForSingleObject( ) debug - release version" which i hav
poste
today
Post by Scott McPhillips [MVP]
Post by James Simpson
Hello
The problem is likely due to threading. If you share one thread with sa
1
Post by James Simpson
active connections and lets say that 2 messages are received at aroun
th
Post by James Simpson
same time (give or take a few milliseconds), since a computer can only d
on
Post by James Simpson
thing at a time it will receive the first incoming message but not th
secon
Post by James Simpson
one, the second message will just be a lost message (in other words th
message would never be received). To solve this problem, create a worke
thread to handle either each socket connection that was created, or fin
way to 'cache' the data that comes into the software. MFC's networkin
an
Post by James Simpson
threading isn't that great (let that be a fair warning). I might sugges
i
Post by James Simpson
this case looking at .NET, because I have heard that .NET is supposed t
solve some of these issues with multithreading and socketing
Sincerely
James Simpso
A coule of corrections to your theory, James
The socket does not lose data. It holds it in a buffer until th
application calls Receive. If the application does not call then th
TCP/IP handshake with the source assures that the buffer will not overrun
CSocket and CAsyncSocket will not work in a worker thread, because the
generate OnReceive/OnSend using the MFC message pump, which is no
present in a worker thread. They require the so-called "use
interface
type of MFC thread
To the original poster: Try calling Receive one time only in eac
OnReceive, and make sure your OnReceive processing does not cal
anything that pumps messages (such as MessageBox). If that does not fi
the problem then it is highly recommended you use CAsyncSocket instea
of CSocket. CSocket is an awkward, terrible, unreliable design
Scott McPhillips [VC++ MVP
Hi, Sakth

I think I also got problem abount CSocket OnReceive not always trigger.
Could you advise me about the solution

How to program "use only one receive() inside OnReceive()." ?
I had set receive timeout for 5 sec. and prepare a large memory for receive(
t
receive 50K bytes, the code is

int timeout = 5000
SetSockOpt(SO_RCVTIMEO, &timeout, sizeof(timeout))

TCHAR msg[409600]
int nRead
nRead = Receive(msg, 409600)


but the first receive also not the all data ,and i need to call Receive(
agai
& again to complete
Couldn't be "use only one receive() inside OnReceive().
tnaks for any advise.

Best Regard

Jackie Hs
***@mail.newimage.com.tw
Joseph M. Newcomer
2011-06-21 13:52:37 UTC
Permalink
Note you only have to ask the question ONCE.
joe
Post by Sakthi
Thanks James for taking time to reply me.
Very kind of u Scott. I tried to use only one receive() inside OnReceive().
Now, it is working fine. Also, advanced thanx to u for going to solving my
problem "WaitForSingleObject( ) debug - release version" which i have posted
today.
Post by James Simpson
Post by James Simpson
Hello,
The problem is likely due to threading. If you share one thread with say
10
Post by James Simpson
active connections and lets say that 2 messages are received at around
the
Post by James Simpson
same time (give or take a few milliseconds), since a computer can only do
one
Post by James Simpson
thing at a time it will receive the first incoming message but not the
second
Post by James Simpson
one, the second message will just be a lost message (in other words the
message would never be received). To solve this problem, create a worker
thread to handle either each socket connection that was created, or find
a
Post by James Simpson
way to 'cache' the data that comes into the software. MFC's networking
and
Post by James Simpson
threading isn't that great (let that be a fair warning). I might suggest
in
Post by James Simpson
this case looking at .NET, because I have heard that .NET is supposed to
solve some of these issues with multithreading and socketing.
Sincerely,
James Simpson
The socket does not lose data. It holds it in a buffer until the
application calls Receive. If the application does not call then the
TCP/IP handshake with the source assures that the buffer will not overrun.
CSocket and CAsyncSocket will not work in a worker thread, because they
generate OnReceive/OnSend using the MFC message pump, which is not
present in a worker thread. They require the so-called "user interface"
type of MFC thread.
To the original poster: Try calling Receive one time only in each
OnReceive, and make sure your OnReceive processing does not call
anything that pumps messages (such as MessageBox). If that does not fix
the problem then it is highly recommended you use CAsyncSocket instead
of CSocket. CSocket is an awkward, terrible, unreliable design.
Scott McPhillips [VC++ MVP]
Hi, Sakthi
I think I also got problem abount CSocket OnReceive not always trigger..
Could you advise me about the solution ?
How to program "use only one receive() inside OnReceive()." ??
I had set receive timeout for 5 sec. and prepare a large memory for receive()
to
int timeout = 5000;
SetSockOpt(SO_RCVTIMEO, &timeout, sizeof(timeout));
TCHAR msg[409600];
int nRead;
nRead = Receive(msg, 409600);
but the first receive also not the all data ,and i need to call Receive()
again
& again to complete.
Couldn't be "use only one receive() inside OnReceive()."
tnaks for any advise..
Best Regards
Jackie Hsu
Joseph M. Newcomer [MVP]
email: ***@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
jaky
2011-06-21 09:19:45 UTC
Permalink
Sakthi wrote on 02/04/2005 14:23 ET
Post by Sakthi
Hai
I am having problem with OnReceive notification of my own class derive
from CSocket. I created a thread, and attaches many client sockets to th
thread (accepting clients in another thread, and posting a message to thi
thread to attach). Now, my OnReceive notification, has not always called
Some times, it is called, and some times, I dont know, why it is not called
Can anybody answer
Hi, Sakth

I think I also got problem abount CSocket OnReceive not always trigger.
Could you advise me about the solution

How to program "use only one receive() inside OnReceive()." ?
I had set receive timeout for 5 sec. and prepare a large memory for receive(
t
receive 50K bytes, the code is

int timeout = 5000
SetSockOpt(SO_RCVTIMEO, &timeout, sizeof(timeout))

TCHAR msg[409600]
int nRead
nRead = Receive(msg, 409600)


but the first receive also not the all data ,and i need to call Receive(
agai
& again to complete
Couldn't be "use only one receive() inside OnReceive().
tnaks for any advise.

Best Regard

Jackie Hs
***@mail.newimage.com.tw
Joseph M. Newcomer
2011-06-21 13:51:56 UTC
Permalink
First rule of network programming: DO NOT use CSocket
Second rule of network programming: if you think you want CSocket, consult the First Rule.

Do no ever consider CSocket as a viable means of writing network programs. CAsyncSocket
is the only working mechanism. CSocket as a paradigm sucks, and besides, the MFC
implementation has bugs. Avoid it. There is no point in trying to "fix" a program that
uses CSocket, except by rewriting it to use CAsyncSocket.
Post by Sakthi
Hai,
I am having problem with OnReceive notification of my own class derived
from CSocket. I created a thread, and attaches many client sockets to the
thread (accepting clients in another thread, and posting a message to this
thread to attach). Now, my OnReceive notification, has not always called.
Some times, it is called, and some times, I dont know, why it is not called.
Can anybody answer?
Hi, Sakthi
I think I also got problem abount CSocket OnReceive not always trigger..
Could you advise me about the solution ?
How to program "use only one receive() inside OnReceive()." ??
I had set receive timeout for 5 sec. and prepare a large memory for receive()
to
int timeout = 5000;
SetSockOpt(SO_RCVTIMEO, &timeout, sizeof(timeout));
TCHAR msg[409600];
int nRead;
nRead = Receive(msg, 409600);
****
First, it is not clear why you repeated the number twice. Have you ever heard of #define
or const UINT?

Second, the chances of ever receiving more than 1536 bytes is zero. That is the size of
an Ethernet packet. But you might receive fewer bytes. There is no reason you should
expect the Receive, as written, to work.
****
but the first receive also not the all data ,and i need to call Receive()
again
& again to complete.
****
Yes, this is how you program sockets. There is NO GUARANTEE that a Receive will EVER
receive what has been sent in a single operation. The only guarantee is that you will
receive all the bytes, in order, with no duplicates, or both the sender and receiver will
get an error message.

Note that the number of times you need to call Receive is undefined; it is up to you to
determine when you have read all the data. This is why most protocols include a count of
the transmission size. Note that the count, if sent as a multibyte field, could be split
between two Receive calls, where one receives the first part of the field and another
Receive receives the rest of the field.

There is no way to change this behavior, since it is built in to how network programming
works. If you expect to send 409600 bytes, you might expect to execute at least 266
Receive calls to receive it, perhaps a lot more.

This will not change if you go to CAsyncSocket, except that now you will understand better
why this can happen.
****
Couldn't be "use only one receive() inside OnReceive()."
****
Not in this world. I'm not even sure why you would expect to be able to do this, given
how sockets are defined to work. You DID read about socket programming, didn't you?

WHat you described is not a "problem" it is "the way sockets work".

But throw out CSocket. It is a poor choice of mechanism. NEVER use CSocket. Or
synchronous sockets.
joe
****
tnaks for any advise..
Best Regards
Jackie Hsu
Joseph M. Newcomer [MVP]
email: ***@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
ScottMcP [MVP]
2011-06-21 14:53:09 UTC
Permalink
Use only one Receive() call inside OnReceive()...

http://support.microsoft.com/kb/185728

It means save the data you get from Receive(), then append to it the
next time you get an OnReceive() call.
Joseph M. Newcomer
2011-06-21 15:17:24 UTC
Permalink
I figured the OP would discover this when the necessary rewrite to CAsyncSocket was done.
joe
Post by ScottMcP [MVP]
Use only one Receive() call inside OnReceive()...
http://support.microsoft.com/kb/185728
It means save the data you get from Receive(), then append to it the
next time you get an OnReceive() call.
Joseph M. Newcomer [MVP]
email: ***@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm

Loading...