Archived

This topic is now archived and is closed to further replies.

Character delimited packets?

This topic is 5527 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have an application that has creates one persistant TCP/IP connection to a server application. Unfortunantly the server application was written many years ago and it only allows one connection from the client computer... That said... Now my application has an internal queue, once the queue has a message it is sends out to the server application. Now if my application sent out 5 messages, the server will not return them in the same order they where sent in, which is ok because the messages have an id within them to be identified... Note: The messages are sent out one after the other since I use synchronus sockets and send() is called once for every message... Now the question is when my application receives back the responses for those messages... My receive loop has been programmed to look for a specific character once it finds that caharcter it assumes the message is complete. The issue is if the server responds back with more then 1 message is it possible that the packets of those messages get intertwinted, like recives 5 bytes from one message another 10 from the other etc...? Or will TCP/IP make sure at least that all the packets fro one message go through before the other message comes in...

Share this post


Link to post
Share on other sites
quote:

Now if my application sent out 5 messages, the server will not return them in the same order they where sent in


If you''re using TCP, then the messasges are guaranteed to arrive in the same order as they are sent. That''s because TCP is a stream based protocol, and have no sense of packets.
quote:

The issue is if the server responds back with more then 1 message is it possible that the packets of those messages get intertwinted, like recives 5 bytes from one message another 10 from the other etc...? Or will TCP/IP make sure at least that all the packets fro one message go through before the other message comes in...


As said above, TCP is stream based, and has no sense of individual packets (nor start or beginning if them). If you send two (or more) packets directly after each other, the sending computer may even put them in one single message before sending them. That''s because there are no real packets, but a stream of bytes.

I get the impression that you lack one important feature: a header. You said you send an ID along with the message to identify it. That''s great. When extracting the information, it''s really good to know how many bytes to expect. That''s what the header is for; to send information to descibe what''s comming. For example, your header could look something like this.

  
struct my_header
{
short ID;
short length;
};

Fill in the structure with proper ID and the length of the data to send, and then send it along with the data. Before the data that is. When receiving, just extract the header, and read the length-field to see how many bytes the message consists of.

Share this post


Link to post
Share on other sites
That the problem this protocol doesn''t work with a header it works as character delimited. If I were to put a header infront of the message the receiving server would not recognize the format anymore. Now I canot tell a bank change your format!

Also when I say send several "messages" one after the other, the server on the other side doesnt guarantee that the responses will come back in the same order. So If sent messages 1,2,3,4,5 I might get them back as 5,2,3,1,4. This is not at the packet level...

Now the problem is, if the server sends back to me 2 "mesages" and tcp/ip splits the messages in 2 packets where the entire first message is the the first packet and a few bytes of the seconds message are also included in the first packet, then in the second packet is the rest of the second message how would I handle that?

Rember the protocol is character delimited...

An easier question would be...

If I do the following in my code...

send(sock, "hello", ....);
send(sock, " world", ...);

will tcp/ip append bytes of buff2 to the packet of buff1?
Is it possible the server on the other side might receive "hello wo" and "rld"or will tcp/ip at least make sure that "hello" get there first and then "world"?

Share this post


Link to post
Share on other sites
quote:

If I do the following in my code...

send(sock, "hello", ....);
send(sock, " world", ...);

will tcp/ip append bytes of buff2 to the packet of buff1?


It will send what you tell it to send. No more, no less. If you tell it to send the ten letters H, E, L, L, O, W, O, R, L and D (in that specific order), then it will do so, without any modifications what so ever.

Remember what I said above, TCP does not work with messages, it's a stream based protocol. The receiver will receive the buffer "helloworld" as if it were a small part of a huge buffer. There are no such thing as "packets" in TCP. If you want to split the string in two, you have to provide a mechanist to do so yourself, cause TCP won't help you. Either use a header as mentioned above (which I understand now is out of the question, but in general), or send an extra delimiter similar to a null terminator.

Just by sending two buffers like that, without any header or delimiter, or anything else to identify the two strings, won't work.

[edited by - Brother Bob on October 17, 2002 4:59:37 PM]

Share this post


Link to post
Share on other sites
Ok fine but am saying if do the 2 sends one after the other like shown previously...

Will recv for example retun "hello wo", which then requires a second call to recv to get the rest of the stream "rld"

[edited by - ANSI2000 on October 17, 2002 5:15:00 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:
Original post by ANSI2000
Ok fine but am saying if do the 2 sends one after the other like shown previously...

Will recv for example retun "hello wo", which then requires a second call to recv to get the rest of the stream "rld"



Recv will return as many bytes as have gotten across the network so far. That could be one string, both strings, or perhaps even one byte per recv.

You need to check the size returned by recv and do the right thing.

Share this post


Link to post
Share on other sites
This question comes up literally every week. With TCP forget the word "packet". There is no such thing. You''re "Hello world" could arrive as:

"Hello "-"world" or
"He"-"llo world" or
"Hello worl"-"d" or
"H"-"e"-"l"-"l"-"o"-" "-"w"-"o"-"r"-"l"-"d"

or as any other permutation you could think of *regardless* of how many sends you did originally. You need to be prepared to buffer partial messages and handle multiple messages arriving in a single recv.

-Mike

Share this post


Link to post
Share on other sites
wait, does this apply to non-blocking servers?

my server uses select() to find out if any data needs to be recv''d, then i recv() it.

--Fireking

Owner/Leader
Genetics 3rd Dimension Development

Share this post


Link to post
Share on other sites
Non-blocking sockets have the same problem.

All select tells you is that some data has been received, it could be 1 byte or 1000. You won''t know until you check the value returned by recv().

Share this post


Link to post
Share on other sites
Buffers.

Buffers.

Buffers.

Seems like every second post I put in this forum is explaining that you need to keep a buffer for every TCP socket, collect the input into that buffer, and process it from there. I can''t think of a single reason why you wouldn''t want to do this unless your application is totally trivial (eg. echo everything to the screen).

Maybe the problem is that too many people are aware of the term ''packet'' or even ''message'' and therefore assume that everything they send and receive comes in little packets. TCP is designed to hide all that from you so that you don''t have to worry about checking sequence numbers and sending acknowledgements and requesting re-sends and buffering out-of-order packets and and and... you just have to accept that the downside is that the data will trickle through at a rate dictated by your TCP implementation, your network settings, network card, the settings on every computer between you and the sender, the sender''s settings, and the program that sent the data... The individual bytes you send down a TCP connection will come in the order they were sent, or not at all, but that''s the only assumption you can really make with any degree of certainty.

[ MSVC Fixes | STL | SDL | Game AI | Sockets | C++ Faq Lite | Boost | Asking Questions | Organising code files | My stuff ]

Share this post


Link to post
Share on other sites
Here is what i do for a protocol that has a length header at the begining...


      
DWORD WINAPI XXXXService::XXXXReadThread(LPVOID p)
{
char inBuffer[1024];
int inBufferLength = 1024;
ZeroMemory(inBuffer, 1024);
char tempBuffer[4096];
ZeroMemory(tempBuffer, 4096);
char dataLengthBuffer[4];
ZeroMemory(dataLengthBuffer, 4);
int dataLength = 0;
int bytesReceived = 0;
int totalBytesReceived = 0;
// Used to compute the value of the incomming message header length.

// HWH = High WORD High BYTE

// HWL = High WORD Low BYTE

// LWH = Low WORD High BYTE

// LWL = Low WORD Low BYTE

DWORD computedLength = 0, HWH = 0, HWL = 0, LWH = 0, LWL = 0;
bool lengthComputed = false;
int queueIndex = 0;
bool read = false;
bool queued = false;

char readDump[1024];

while(thisXXXXService->getStatus())
{
if(thisXXXXService->XXXXSocketConnected)
{
dataLength = 0;
bytesReceived = 0;
totalBytesReceived = 0;
lengthComputed = false;
read = false;
queued = false;

try
{
printf("Read - Waiting to receive data from XXXX...\n");

while((totalBytesReceived - 4) < dataLength)
{
bytesReceived = thisXXXXService->FEDSSocket.read(inBuffer, inBufferLength);
inBuffer[bytesReceived] = 0;

if(!lengthComputed)
{
printf("Read - Computing buffer length...\n");
WaitForSingleObject(thisXXXXService->logMutex, INFINITE);
Utilities::getInstance()->log(thisXXXXService->logsLocation, "Read", "Computing buffer length...\n");
ReleaseMutex(thisXXXXService->logMutex);
memcpy(dataLengthBuffer, inBuffer, 4);
dataLengthBuffer[4] = 0;

computedLength = 0;
HWH = 0;
HWL = 0;
LWH = 0;
LWL = 0;

// Compute the length of the message received from XXXX.

HWH = dataLengthBuffer[2] & 0x000000FF;
HWL = dataLengthBuffer[3] & 0x000000FF;
LWH = dataLengthBuffer[0] & 0x000000FF;
LWL = dataLengthBuffer[1] & 0x000000FF;
computedLength = ((HWH << 24) | (HWL << 16) | (LWH << 8) | LWL);

dataLength = computedLength;

printf("Read - Buffer length computed: %d.\n", dataLength);
WaitForSingleObject(thisXXXXService->logMutex, INFINITE);
Utilities::getInstance()->log(thisXXXXService->logsLocation, "Read", "Buffer length computed.\n");
ReleaseMutex(thisFEDSService->logMutex);

lengthComputed = true;
}

memcpy((tempBuffer + totalBytesReceived), inBuffer, bytesReceived);
totalBytesReceived += bytesReceived;
}

tempBuffer[totalBytesReceived] = 0;

sprintf(readDump, "Received: %s\n", (tempBuffer + 4));
printf("Read - %s", readDump);
WaitForSingleObject(thisXXXXService->logMutex, INFINITE);
Utilities::getInstance()->log(thisXXXXService->logsLocation, "Read", readDump);
ReleaseMutex(thisXXXXService->logMutex);

read = true;
}
catch(WinsockException &ex)
{
printf("Read - Error occured while reading data from FEDS.\n%s", ex.getExceptionMessage(__FILE__, __LINE__));
WaitForSingleObject(thisXXXXService->logMutex, INFINITE);
Utilities::getInstance()->log(thisXXXXService->logsLocation, "Read", ex.getExceptionMessage(__FILE__, __LINE__));
ReleaseMutex(thisXXXXService->logMutex);

thisXXXXService->XXXXSocketConnected = false;
thisXXXXService->XXXXSocket.closeSocket ();
}


See this is part of the solution this code is stil rpon to not receiveing and creating the proper messages out of the stream... What esle can be done to make it better?

[edited by - ANSI2000 on October 18, 2002 9:44:42 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by Anon Mike
This question comes up literally every week. With TCP forget the word "packet". There is no such thing. You''re "Hello world" could arrive as:

"Hello "-"world" or
"He"-"llo world" or
"Hello worl"-"d" or
"H"-"e"-"l"-"l"-"o"-" "-"w"-"o"-"r"-"l"-"d"

or as any other permutation you could think of *regardless* of how many sends you did originally. You need to be prepared to buffer partial messages and handle multiple messages arriving in a single recv.

-Mike



what about doing a

send(socket,"1",1,0);//indicates beginning of a message
send(socket,"kljsjdflkjsd",12,0);//send our message
send(socket,"0",1,0);//indicates end of a message

or will winsock break up 1''s and 0''s too?

  
int br;
char *buffer;
br=recv(socket,buffer,1,0);
if(buffer=="1")
{
//some how start a message

}
//some how check br then ?recv again? to get the entire message?

//append that crap to a static buffer ???

if(buffer=="0")
{
//some how end a message

}

help me out here?

--Fireking

Owner/Leader
Genetics 3rd Dimension Development

Share this post


Link to post
Share on other sites
quote:

what about doing a

send(socket,"1",1,0);//indicates beginning of a message
send(socket,"kljsjdflkjsd",12,0);//send our message
send(socket,"0",1,0);//indicates end of a message

or will winsock break up 1''s and 0''s too?


It has been said a few time already, but I say it again: TCP does not work in messages or packets or anything like that. It works with a stream of bytes. If you send the buffer "1kljsjdflkjsd0", that buffer will show up in the end. You may have to call recv a few times, but i WILL show up in one way or another. That''s the only think you can know for sure. It doesn''t matter whether you send them one byte at a time (one byte per call to send()), or the whole buffer on one send. If your computer thinks it''s most efficient to send it in parts, then it will send it in parts. If it think it''s more efficient to send it in one go, then it will do so.

To the other end, these three pieces of code are exactly the same. There is no way to detect with 100% acuracy which of these methord was used.

  
send(socket,"1kljsjdflkjsd0",14,0);


send(socket,"1kljsjd",7,0);
send(socket,"flkjsd0",7,0);


send(socket,"1kl",3,0);
send(socket,"jsjdflkj",8,0);
send(socket,"sd0",3,0);

The code you posted will work, since you first extract one byte from the stream, and check whether it''s a "1" or not (not counting the way you do the actual comparison, but hey ). Don''t think about it as receiving packets or messages, think of it as extracting bytes from a stream.

Share this post


Link to post
Share on other sites
quote:
Original post by Brother Bob
what about doing a

send(socket,"1",1,0);//indicates beginning of a message
send(socket,"kljsjdflkjsd",12,0);//send our message
send(socket,"0",1,0);//indicates end of a message

or will winsock break up 1''s and 0''s too?
It has been said a few time already, but I say it again: TCP does not work in messages or packets or anything like that. It works with a stream of bytes.


why do you keep telling us there are no such things as messages? I KNOW THAT. Im talking about messages as in "in our protocol, a single message, is ideally what we want to send." It is a single entity, an object if you well, that we are sending. I know TCP is stream based, but for the sake of simplicity i say message as the server would see it. The server is saying, "Hey im sending one thing to the client right now, the client has programmed what will happen when i send this one thing to him." Thats what i mean by message...

either way, the problem is still unsolved.

--Fireking

Owner/Leader
Genetics 3rd Dimension Development

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
TCP (well, IP or pretty much and network protocol) sends and receives bytes (8 bit) of data, no smaller. So, sending a single character, such as "1" will eb guaranteed to be received as a "1" and not half a byte or anything. I would''ve thought that was fairly straightforward since you can only send and receive to winsock in bytes anyway...

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:
Original post by fireking
why do you keep telling us there are no such things as messages? I KNOW THAT. Im talking about messages as in "in our protocol, a single message, is ideally what we want to send." It is a single entity, an object if you well, that we are sending. I know TCP is stream based, but for the sake of simplicity i say message as the server would see it. The server is saying, "Hey im sending one thing to the client right now, the client has programmed what will happen when i send this one thing to him." Thats what i mean by message...

either way, the problem is still unsolved.



You still seem confused. You''re asking questions about when TCP ''breaks up'' messages, then you say you know that TCP isn''t message based.

TCP knows nothing about your server''s messages. It will divide or merge your server''s messages as it sees fit. Write your client to anticpate all eventualities. One message per recv, half a message per recv, one and a half messages per recv, etc.

If this doesn''t answer your question, please rephrase.

Share this post


Link to post
Share on other sites
why doesnt anyone just show an example?

i dont understand the fact that all of you know what you are talking about, but back it up with no code...

i want to send a message. I dont care of tcp doesnt have any concept of messages, i want to MAKE it have a concept of messages. Someone some where has done this, even the microsoft winsock control does what im wanting to do. When i send something, i want the client to recieve it exactley how i sent it. All of you say you have to write to a buffer until all of the data is recieved or something. Well how about showing me how to do that instead of nagging at me about stupid "tcp has no concept of mesages".

--Fireking

Owner/Leader
Genetics 3rd Dimension Development

Share this post


Link to post
Share on other sites
The way you delimit single messages is by knowing what they look like.

If you know to expect 4-byte floating point numbers, you buffer input until you have 4 bytes. Then you remove those bytes from the buffer, and use them for a float.

If you know to expect three successive long integers, then you read each of those, one at a time.

If you want to send EITHER a float OR three integers, first you send a character describing whether you''re sending a float or integers. The reciever knows to expect that byte, looks at it, and based on its contents either expects a float next or expects integers next.

If you''re sending a string (or an array of anything else), you could send it zero-terminated, you I could send the size first, so that the reciever knows how many characters to treat as the string (array).

If you''re sending a structure, you know what order you send the fields in, so recieve them in the same order.


Don''t listen to me. I''ve had too much coffee.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
If you don''t know how to create a buffer and write to it, perhaps you should be asking in the General Programming or For Beginners forums.

Share this post


Link to post
Share on other sites
I''ve already posted some code in another thread that will treat TCP as a message based protocol, by breaking up the stream. Since you didn''t understand it, I will try again. I will also try to make it more complete and less pseudo-code. I don''t have a complier available right now, so there might be some errors mostly because I''m doing this from memory and don''t remember the exact parameters to the socket functions. Most importantly the code is missing some error checking (such as not checking the return values of all the socket functions).

The code uses an 8 byte header (below) followed by the actual message:
4 byte integer to identify the "type" of message
4 byte integer to identify the size of the message in bytes (not including the header)


  
struct Message
{
int type;
int size;
char *msg;
};



Function to send a message.

  
void SendMessage(SOCKET s, Message *msg)
{
int msgType = htonl(msg->type);
int msgSize = htonl(msg->size);

send(s, &(msg->type), sizeof(int)):
send(s, &(msg->size), sizeof(int));
send(s, msg->msg, msg->size);
}


Function to receive a message.
Returns a new Message or NULL if there was an error.

  
// ReceiveBytes will wait until bufferSize bytes has been

// received, returning false if an error occurs.

bool ReceiveBytes(SOCKET s, char *buffer, int bufferSize)
{
int bytesRecieved = 0;

// Get the message type

while (bytesReceived < bufferSize)
{
// call recv, asking for the number of bytes we require

// to fill up the type field (sizeof(int))

int size = recv(s, buffer + bytesReceived, bufferSize - bytesReceived));

if (size <= 0) {
return false;
}

bytesReceived += size;
}

return true;
}

Message *ReceiveMessage(SOCKET s)
{
int msgSize, msgType;

// Read the message type

if (!ReceiveBytes(s, (char *)&msgType, sizeof(int)))
return NULL;

// Read the message size

if (!ReceiveBytes(s, (char *)&msgSize, sizeof(int)))
return NULL;

// Now that we know how long the message is,

// get the rest of the message

Message *msg = new Message;
msg->type = msgType;
msg->size = msgSize;
msg->msg = new char[msg->size];

if (!ReceiveBytes(s, msg->msg, msg->size))
{
delete [] msg->msg;
delete msg;
return NULL;
}

return msg;
}


Any questions?

Share this post


Link to post
Share on other sites