|
Oh, and I don't think the line
delete x, d;
is doing what you think it is doing
|
|
|
|
|
That is one tricky expression!
--
Kein Mitleid Für Die Mehrheit
|
|
|
|
|
It's hard to tell without being able to see how you defined "d", but are you using
a reference or pointer type?
For example, this works as expected:
A* x = new B();
deque<A*> d;
d.push_back(x);
for(deque<A*>::iterator itD = d.begin(); itD != d.end(); itD++)
{
(*itD)->test();
}
delete x;
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Mark Salsbery wrote: but are you using
a reference or pointer type?
Can't you just assume he is? I think they should just add 'assume' as a C++ keyword, that would solve a lot of CodeProject questions.
Great fishing today eh? I bet you can bag your limit in like 5 minutes. Last modified: 14mins after originally posted --
|
|
|
|
|
led mike wrote: Great fishing today eh?
Actually it's been great for quite a while now....must be related to global warming
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Mark Salsbery wrote: must be related to global warming
fatboy's going to get you for that!
|
|
|
|
|
led mike wrote: fatboy
Exactly...I'm trolling for the big one!
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Edit your post so the "<" and ">" characters and what's between them can be seen! I can’t see what files you’re including or what specialization of deque you’re instantiating. This information is obviously important. Do you review your posts or what?
Steve
|
|
|
|
|
Hey all,
I wrote a simple TCP server client application, where client is sending some text to the server.
I based the implementation on Nish's article: http://www.codeproject.com/internet/winsockintro02.asp.
But I have one problem. For example, when I want to send data "hello" to server, I use the send(..) method, for which I have a correcsponding receive(..) method on the server side.
My problem is that if I want to send for example two data objects: "hello" and "hello again", with two 1. send("hello",..); 2. send("hello again",..); and two receive(..); receive(..); methods. I am still not managing to receive data on the server side in the appropriate order. Sometimes I will receive "hellohelloagain" sometimes I will receive data as I had sent them, i.e. "hello" and "helloagain".
Can anyone give me a clue how to implement the program such that I can seperately send differenttext data from client, i.e. text[1], ...., text[n] and easily receive this data in the same manner, on the server side ?
Thanks.
|
|
|
|
|
TCP is a stream based protocol - it only understands a stream of bytes.
It's up to you to parse the bytes into meaningful sequences.
You need to design a protocol on top of TCP so the receiving end knows how many bytes to expect.
This could be a fixed-length "packet" scheme.
A simple, more effiicient scheme is to pass the data length first (for example, a 4-byte int - don't forget
byte order issues!) before passing the data. The receiving end first receives the count, then it knows how
many bytes follow.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Thanks Mark. I thought so...
What I am currently doing is receiving text seperated by ";" and parse them appropriately..
|
|
|
|
|
How do you do that efficiently without knowing how many bytes to receive?
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
I just assume that the maximum length of text should be 512 bytes, for example. Not sure if it is very efficient
|
|
|
|
|
bigdenny200 wrote: Not sure if it is very efficient
I would imagine it is not
At some point, the TCP protocol has to decide it's waited long enough for
512 bytes and just return what it's received so far. I'm not sure what that
timeout value is (or how it decides) but it's certainly less efficient than knowing
the exact count to recv.
Also, make sure you follow Judy's advice... it is theoretically possible for recv() to
receive one byte at a time! Your recv() logic MUST be in a loop, or allow for partial receives
some other way. Another reason knowing the exact length to receive is good
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Dear Mark,
I got a bit confused. Let me ask you one thing. In previous replies you mention,
"a fixed-length "packet" scheme". For example I want to send text: "hiu","bye","guy"
seperately. Ans assume I call them using three respectivesend calls.
The server knows it should get 3 bytes at a time. So I have
while ( i = recv(buff, 3,..) )
{...}
My question is, does this way guarantee me that first time buffer will contain
"hiu", second time "bye", etc. ?
Also, what do you mean by: "a 4-byte int - don't forget byte order issues!" In your previous reply ? As I can see I am not of appropriate knowledge
Thanks
|
|
|
|
|
bigdenny200 wrote: you mention,
"a fixed-length "packet" scheme"
By that, I meant, for example, a structure (which is fixed length) - since the sender sends a structure,
the receiver knows to receive sizeof(thestructure) bytes. This is inefficient if the structure isn't always
fully used, since there will be needless extra bytes sent across the network.
bigdenny200 wrote: The server knows it should get 3 bytes at a time. So I have
while ( i = recv(buff, 3,..) )
{...}
The problem here (that Judy was referring to) is that a recv() call is successful
even if only ONE byte is received. Even though the sender sent 3 bytes, that doesn't
mean the receiver receives 3 bytes. TCP guarantees you'll eventually get the 3 bytes, in order,
but there's no guarantee they will come in one call to recv(). Remember, TCP only knows bytes.
Here's an example, with some error checking, of a way to receive a known number of bytes into a BYTE buffer...
int BytesRemaining = # of expected bytes;
BYTE *pCurBuf = start address of buffer to recv bytes into;
while (BytesRemaining > 0)
{
int CurBytesReceived = ::recv(hSocket, (char*)pCurBuf, BytesRemaining, 0);
if (CurBytesReceived == 0)
{
break;
}
else if (nCurBytesReceived == SOCKET_ERROR)
{
int rc = WSAGetLastError();
if (rc != WSAEWOULDBLOCK)
{
break;
}
}
else
{
BytesRemaining -= CurBytesReceived;
pCurBuf += CurBytesReceived;
}
}
bigdenny200 wrote: what do you mean by: "a 4-byte int - don't forget byte order issues!"
If you ever pass multibyte integers between different platforms, you need to
worry about byte order. For example, Intel machines store ints in memory with
the least-significant byte first. It's opposite on non-Intel Macs. If you stream the
4 bytes of the int from one platform to the other, the receiver needs to know to swap the
byte order before using the 4 bytes as an int.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Dear Mark, thank you for your (very) helpful replies.
I will try to run the code tomorrow, and see what I get.
Thanks for the other hint as well, but believe me I just prey
this thing to work only for Windows
|
|
|
|
|
bigdenny200 wrote: I just prey
I would pray instead
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
You are best off by buffering the incoming data, and parse from it. I recommend a ring buffer, preferable one which can hold the biggest possible command (otherwise you won't be able to parse a complete sentence).
Whatever you do, don't read one byte at a time. It is horrendously inefficient.
--
Kein Mitleid Für Die Mehrheit
|
|
|
|
|
Thats what I am doing, but as Mark suggested, the TCP timeout can stop receiving the data, if the buffer is too big?
Did I misundertand something ?
|
|
|
|
|
With a buffer I mean that you should read in fixed sized chunks. Say 512 bytes per chunk (or less, if your sockets are non-blocking, in which you could end up with 0 bytes, should no bytes have been delivered to the reader). After you read data from the socket, parse/continue parsing the buffer. Once you find the packet you are looking for, remove it from the buffer, and keep the rest of the buffer (might be a partial packet).
|
|
|
|
|
In addition to what Mark said, don't expect your Receive call (whatever your particular API is - recv in plain old sockets) to receive all the bytes sent in a single call by the Send. You might get "hel" then "lohelloa" then "gain" in consecutive calls. You must code your receiving logic to handle rebuilding the entire packet that Mark is talking about.
Judy
|
|
|
|
|
Hi JudyL_FL,
I am not sure if I understand what do you mean, by:
"You must code your receiving logic to handle rebuilding the entire packet that Mark is talking about."
I am just using one recv() , so you mean that it is possible that I just get: "hell" and nothing else? Note, I am calling recv() only once.
Thanks.
|
|
|
|
|
bigdenny200 wrote: I am just using one recv(), so you mean that it is possible that I just get: "hell" and nothing else? Note, I am calling recv() only once.
Exactly. There is no guarantee that a single recv call on one end of a connection will get all the data sent with a single send call on the other end. Looking at the reply you sent to Mark, you need to keep calling recv until you get your "end of packet" marker ;. Handle that packet somewhere somewhen and repeat the process.
Judy
|
|
|
|
|
JudyL_FL wrote: There is no guarantee that a single recv call on one end of a connection will get all the data sent with a single send call on the other end.
It is possible with fixed sized messages, and blocking sockets. Although, I don't think the message sizes are fixed, because he mentions parsing messages, separated with a ;
--
Kein Mitleid Für Die Mehrheit
|
|
|
|