Jump to content
  • Advertisement
Sign in to follow this  
Exustio

[solved] All data not being transferred (TCP)

This topic is 3160 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

Well I have a simple problem that occur when I increase the amount of data needed to be transferred. I have heard something about that it isn't possible to send too large amounts of data with the send()-function in one call, at the same time I have heard that send automaticly splits and merges the data. However if I am supposed to split the data needed to be transferred into several send(), how large should I make each part? Anyhow the problem I get when I increase the size of "TSquare" is that the whole "ClientMap" isn't updated when I call send/recv, instead of it working well as with the smaller version, only half of the map is updated with the larger version. First, here are the datastructs that I am trying to send from the server to the client.
struct TSquare {              // This is the old, smaller one that works
  unsigned short  ground;
  unsigned short  object;
};

struct TSquare {            // This is the new one that causes the problems      
  unsigned short  ground;
  unsigned short  object;
  unsigned short  NPC;
  byte            roof;
  bool            canWalk; 
};

struct TClientMap {
  TSquare square[23][19];
};



And the Send() / Recv()
send(client->socket, (char*)&userData->clientMap, sizeof(TClientMap), 0);  // "clientMap" is a variable of the type "TClientMap"



recv(clientSocket, (char*)&ClientMap, sizeof(TClientMap), 0);



There is probably a really simple solution to this, but I haven't found it when looking through the forums so I hope someone of you can help me. [Edited by - Exustio on October 28, 2009 8:41:45 AM]

Share this post


Link to post
Share on other sites
Advertisement
Also, send isn't guaranteed to send all the given bytes at once - it too returns the number of bytes sent (or an error indicator). You need to check this too and buffer the unsent data, and try to send it later (perhaps when a call to select indicates the socket is writable)

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
recv() returns the number of bytes read from the socket, which may not be as many as you request. What does recv() return?

Most of the time it returns 3496 which it should, but every now and then it returns 1460, which is the same time as the map isn't fully updated.

Quote:
Original post by mattd
Also, send isn't guaranteed to send all the given bytes at once - it too returns the number of bytes sent (or an error indicator). You need to check this too and buffer the unsent data, and try to send it later (perhaps when a call to select indicates the socket is writable)

I thought the whole point with blocking was that it would wait until everything was sent / received

Share this post


Link to post
Share on other sites
If the socket is blocking, it should block until all data is sent / received, yes.

Does send() always return 3496?

You could also fire up Wireshark and see what data is actually being sent.

Share this post


Link to post
Share on other sites
Quote:
Original post by Exustio
I thought the whole point with blocking was that it would wait until everything was sent / received


In that case, sending will block as necessary. But reading won't.. how will it know when an entire 'message' is received? (TCP is a stream protocol, and message boundaries are not preserved).

You need to tell the client, via a message of some sort, what the size of the map is - be it in map dimensions, or its serialized byte stream size. The client can then continuing reading the socket until it knows the entire map has been downloaded.

Share this post


Link to post
Share on other sites
Quote:
Does send() always return 3496?

yes, send always returns 3496
Quote:
You need to tell the client, via a message of some sort, what the size of the map is - be it in map dimensions, or its serialized byte stream size. The client can then continuing reading the socket until it knows the entire map has been downloaded.

I thought I did that with the 3rd parameter of recv, or do I need to loop the recv call until I have counted up to sizeof(TClientMap)?

Share this post


Link to post
Share on other sites
Quote:
Original post by Exustio
I thought I did that with the 3rd parameter of recv, or do I need to loop the recv call until I have counted up to sizeof(TClientMap)?


That only specifies the buffer size, ie. the maximum amount of data it can read and give to you at once. So yes, you do.

You can ignore what I said previously about having to send the map size first, because upon re-reading your OP I see that the map is a static size, so as long as its definitions remain the same on the server and the client, reading sizeof(TClientMap) will suffice.

Share this post


Link to post
Share on other sites
It seems like it worked.

I wrote this
  int tmp = 0;
char *buffer = new char[sizeof(TClientMap)];
while (tmp < sizeof(TClientMap))
{
tmp += recv(clientSocket, (char*)&buffer[tmp], sizeof(TClientMap)-tmp, 0);
}
memcpy((char*)&ClientMap, buffer, sizeof(TClientMap));
delete buffer;

Share this post


Link to post
Share on other sites
Quote:
Original post by Exustio
It seems like it worked.

I wrote this
*** Source Snippet Removed ***
You'll want to check for recv() returning 0 or SOCKET_ERROR, but otherwise that looks fine to me.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!