Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

CSocket::OnReceive() getting called only once.

133 views
Skip to first unread message

nexolite

unread,
Jan 12, 2009, 1:20:01 PM1/12/09
to
CSocket::OnReceive() getting called only once .
What can be the reason?

Scott McPhillips [MVP]

unread,
Jan 12, 2009, 2:41:18 PM1/12/09
to
"nexolite" <nexo...@discussions.microsoft.com> wrote in message
news:CBE571AD-6CC1-44DA...@microsoft.com...

> CSocket::OnReceive() getting called only once .
> What can be the reason?

There can be two reasons.

1. If you don't call Receive on OnReceive
2. If no more data arrives.

--
Scott McPhillips [VC++ MVP]

nexolite

unread,
Jan 13, 2009, 12:01:00 AM1/13/09
to
I have a server that makes two consecutive calls to send()
so I have verified by using telnet client that both the strings are received
but my MFC client's program OnReceieve gets called only once, I am calling
Receive to read data but OnReceive itself is not getting called more than
once.

Joseph M. Newcomer

unread,
Jan 13, 2009, 2:47:46 AM1/13/09
to
It doesn't matter HOW MANY send calls one side does; the other side will receive what it
receives. You might do one send() and take 20 receive()s to get the data, or 20 sends()
which all appear on one receive(). It is a stream-oriented protocol and there is NO
CORRELATION between the number of send()s and the number of receive()s.

Note also that if you do
send(1000 bytes);
send(1000 bytes);
send(1000 bytes);

while sending 1000-byte packets, you will quite possibly see
receive(1456 bytes);
receive(1456 bytes);
receive(88 bytes);
or
receive(512 bytes);
receive(512 bytes);
receive(1024 bytes);
receive(952 bytes);

and that's just TWO of the possible scenarios. There is not only no correlation between
the number of sends and number of receives, there is no correlation between the size of
the data in a single send and the size of the data in a single receive. They are
COMPLETELY INDEPENDENT concepts. send() creates a stream of bytes, which are sent out in
bunches of whatever sizes the sending stack chooses to send, which are received by the
receiving stack, and which are reassembled into streams. Depending on the timing, network
traffic, phase of the moon, and number of sunspots, you can get different lengths on a
sequence of successive experiments.

It is a common error to think that size-of-send and number-of-sends correlates in any way
whatsoever with size-of-receive and number-of-receives. The only thing TCP/IP guarantees
is that the receives will receive a sequence of bytes which, ultimately, are in 1:1
correlation with the sequence of bytes sent. But how those are managed in terms of IP
data packets, how send()s are coalesced into outgoing packets, how receive()s get the data
and reassemble it for you, is entirely up to the network stacks, and can vary
minute-by-minute.

Note that if your data format uses a length field, and the length field is a multibyte
value, then it is always possible for a split to happen in the middle of the length field,
and you will have to cope with this. This is typically done by using a slightly modified
finite-state-machine (FSM) model for packet-parsing. I illustrate such an algorithm in my
multithreaded TCP/IP example on my MVP Tips site.
joe

Joseph M. Newcomer [MVP]
email: newc...@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm

nexolite

unread,
Jan 16, 2009, 3:20:05 AM1/16/09
to
Actually OnReceive() itself is not getting called properly or as I say is
getting called only once.
I have made this client code:

class Client:public CDialog
{
public:
Client();
Client(int n):CDialog(n){}
void OnRecieve();
void OnOK();
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(Client,CDialog)
ON_COMMAND(IDOK,OnOK)
END_MESSAGE_MAP()
class ClientSock:public CSocket
{
private:
CDialog *pwnd;
public:
void SetParent(CDialog *mpwnd)
{
pwnd=mpwnd;
}
void OnReceive(int nErrorCode)
{
CSocket::OnReceive(nErrorCode);
AfxMessageBox("from receive()");
if(nErrorCode==0)
((Client*)pwnd)->OnRecieve();
}
}sock;

void Client::OnOK()
{
sock.Create();
if(sock.Connect("127.0.0.1",4945)==FALSE)
MessageBox("error");
}
void Client::OnRecieve()
{
char data[200];
int read=sock.Receive(data,sizeof(data));
data[read]=NULL;
CString Data=data;
MessageBox(Data);
}
class ClientApp:public CWinApp
{
public:
BOOL InitInstance()
{
AfxSocketInit();
Client d(IDD_TEST);
m_pMainWnd=&d;
d.DoModal();
return TRUE;
}
}a;

Is there any problem with this code since its OnReceive() is called only once.

Scott McPhillips [MVP]

unread,
Jan 16, 2009, 7:57:10 AM1/16/09
to
You have two message box calls during OnReceive. That is a problem. After
you call Receive the socket can queue another notification if more data
arrives. But executing MessageBox can let that notification message be lost
or cause reentry into OnReceive, before the first call has returned. Do not
permit the message pump to run until you have returned from OnReceive.
(MessageBox runs the message pump.)


"nexolite" <nexo...@discussions.microsoft.com> wrote in message

news:9E330BC3-60D2-40DE...@microsoft.com...

Joseph M. Newcomer

unread,
Jan 16, 2009, 9:58:35 AM1/16/09
to
First, why are you using CSocket? Not only is this a bad choice, but the MFC
implementation of CSocket is reputed to be very buggy (I have never used it, so I don't
know). You should be using CAsyncSocket. CSocket is a class whose inclusion is probably
a design error in MFC. As far as I can tell, nobody ever wants to do synchronous socket
programming.

Why did you omit this critical piece of information from the original post?

You should probably use TRACE statements instead of messageboxes because messageboxes
create secondary message pumps, never a good idea in a situation like this.

Why is it that your socket code has any idea about what the client is doing. Use
PostMessage to send the information to the client.

See my essay on multithreaded sockets on my MVP Tips site. You can drop the
multithreading, but the rest of it can be used (in fact, the multithreaded example is just
a generalization of a rather straightforward single-threaded CAsyncSocket implementation)
joe

nexolite

unread,
Jan 16, 2009, 11:28:02 AM1/16/09
to
Exactly which one I must read
I read this one :http://www.flounder.com/detach.htm#Sockets
but this doesnt helped as it does not explains CAsyncSocket

Joseph M. Newcomer

unread,
Jan 17, 2009, 12:14:30 AM1/17/09
to
Try the article I suggested on asynchronous sockets:

http://www.flounder.com/kb192570.htm

It is indexed as "asynchronous sockets done right"

Just ignore the threading parts.
joe

nexolite

unread,
Jan 20, 2009, 1:31:01 PM1/20/09
to
Finally I got the problem!

The problem were not the MessageBoxes as now they are now not causing any
problem even I dont close the previously opened MessageBox and the next one
pops up!

THE PROBLEM WAS:
at the server side I was doing this in OnAccept() (only for testing client)

serv.Send();
serv.Send();

Two consecutive calls to Send is a problem and I dont know why the second
send doesnt work if followed immediately.

Then I changed this to:
serv.Send();
MessageBox();
serv.send();

and after this the text from the both the Send()s was received at the client
side.

0 new messages