Jump to content
  • Advertisement
Sign in to follow this  
Tano_ITA

Little problem with WSASend() and Recv()

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

Hi, i'm using WSASend to send messages to all my client connected.

void ServerSystem::PUBLIC_CHAT_MOVEMENT(Client* client, std::string x, std::string y)
{
	WSABUF *msg_buf  = new WSABUF;
	string nickname = client->getId();
	client->setPositionX(atoi(x.c_str()));
	client->setPositionY(atoi(y.c_str()));

	std::vector<Client*>::iterator itl;
	string msg("7_"+nickname+"_"+x+"_"+y);
	msg_buf->buf = const_cast<char*>(msg.c_str());
	msg_buf->len = msg.size();	

	for(itl = client->getGroup()->ClientGroupBegin(); itl != client->getGroup()->ClientGroupEnd(); ++itl)
	{
		WSASend((*itl)->GetSocket(), msg_buf,  1, &m_dwBytes, m_dwFlags, p_ol, NULL);	
	}
	/*LOG_SYSTEM(msg_buf->buf);*/
	delete msg_buf;
}
All client recive this tipe of message: 7_nickname_x_y . But when i send a lot of messages, sometime all client recive this type of message: 7_nickname_x_y7_nickname_x_y. I print the message sended on console and it is always correct. But the client recive sometime a bad message, two merged message.. Anyone can help me? Sorry for my bad english..

Share this post


Link to post
Share on other sites
Advertisement
Quote:
To construct message semantics on TCP, each time you send a message, you have to precede it with the length of the message, as a short or a long (use htons() or htonl() to make it cross-platform). Then write that many bytes of message. On the receiving side, you'd first read out the length (a short or long) and then that many bytes of message data, re-constituting each message sent from the other end.


where i can find an example? I can't undestand how can i send the length of message..

Share this post


Link to post
Share on other sites
Quote:
Original post by Tano_ITA
Quote:
To construct message semantics on TCP, each time you send a message, you have to precede it with the length of the message, as a short or a long (use htons() or htonl() to make it cross-platform). Then write that many bytes of message. On the receiving side, you'd first read out the length (a short or long) and then that many bytes of message data, re-constituting each message sent from the other end.


where i can find an example? I can't undestand how can i send the length of message..
Your for() loop should be:

for(itl = client->getGroup()->ClientGroupBegin(); itl != client->getGroup()->ClientGroupEnd(); ++itl)
{
// Send the length of the buffer we're about to send (As a single u_long)
u_long nLength = msg_buf.len;
WSABUF bufLength;
bufLength.len = sizeof(nLength);
bufLength.buf = (char*)&nLength ;
WSASend((*itl)->GetSocket(), bufLength, 1, &m_dwBytes, m_dwFlags, p_ol, NULL);

// Send the message itself
WSASend((*itl)->GetSocket(), msg_buf, 1, &m_dwBytes, m_dwFlags, p_ol, NULL);
}

Or something similar. basically, you send two buffers, one indicating the length of the data, and one for the data itself. When you WSARecv() from the socket, you read sizeof(u_long) to find out how long the message is, then read that number of bytes.

Note that you'll also need to cope with cases where you don't have enough bytes available yet, and wait until that many bytes are available - usually by keeping a buffer around of the currently extracted bytes.

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
Your for() loop should be:
*** Source Snippet Removed ***Or something similar. basically, you send two buffers, one indicating the length of the data, and one for the data itself. When you WSARecv() from the socket, you read sizeof(u_long) to find out how long the message is, then read that number of bytes.

Note that you'll also need to cope with cases where you don't have enough bytes available yet, and wait until that many bytes are available - usually by keeping a buffer around of the currently extracted bytes.


Just to add a few more comments:

Some games include the packet size as part of the packet itself. So if you were to build your packets like so:
[xx xx][xx xx][xx ... xxx]
size opcode payload

You would just recv() a buffer of data, let's say 8192 bytes since that's pretty large to take enough data on fast connections, and then you process the stream according to that packet protocol. For example, if client sends:
04 00 01 00 't 'e' 's' 't' the server would recv that into a buffer and start processing byte by byte.

I.e., it'd check to see if recv size was > 2 since packet size is contained in 1st two bytes, and if it were, then it knows how much data required to process the current packet (read size + 4 since constant 4 byte header size). If it didn't have enough data, it would return wand wait for the rest of the data, since with TCP, it will eventually get there. If it has enough data, it can then rip out that packet data into another buffer, pass it along, and then memmove the rest of the stream overlapping that data and continue on, recv'ing into the last buffer index to make sure not tt overwrite any existing data.

The important thing to remember when keeping those recv buffers is that they are per connection, not per socket! I.e., each connection should have its own recv buffer that data is copied into from the main recv buffer. Otherwise, different clients can end up overwriting each others data if you use a single static buffer for all data. This may seem trivial, but I made the mistake when I was starting out and only working with one connection total.

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.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!