Sign in to follow this  
geKingu

Error when sending to clients

Recommended Posts

Hey again people. I'm new to network programming and have been experimenting with code examples. I rewrote some client-server program to enable the server to send any message recieved from a client, to all other clients. Originally the server was just a listener. Anyways I've done something wrong, but I'm unsure what. The server program stops responding when it reaches this code:
//check for client activity
		for (i=0; i<MAXCLIENT; i++)
		{
			if (SDLNet_SocketReady(client[i]))
			{
				//We have an incoming message!
				result=SDLNet_TCP_Recv(client[i], message, MAXLEN);

				if (result <= 0)
				{
					cout << "Client " << i << " Disconnected!\n";
					client[i] = NULL;
				}
				else 
				{
					cout << "Client " << i+1 << ": " << message << "\n";
					for (k=0; k<MAXCLIENT; k++)
					{
						if(k != i) {
							len=strlen(message)+1;
							result2=SDLNet_TCP_Send(client[k], message, len);
							if(result2 < len) cout << "Client " << k+1 << " Disconnected!\n";
						}
					}
				}

			}
		}
Specifically when the server tries to send the message to all other clients. The code to recieve messages in the client, looks like this:
if (SDLNet_SocketReady(tcpsock))
		{
			//There is a message from the server!
			//Recieve it

			result=SDLNet_TCP_Recv(tcpsock, message, MAXLEN);

				if (result <= 0)
				{
					cout << "Server Disconnected!\n";
					exit(-1);
				}
				else 
				{
					cout << "Recieved: " << message << "\n";
				}
		}
Is there a better way for me to send messages from server to client? Should I use a seperate socket for sending and receiving? Any help would be appreciated :) ~geKingu

Share this post


Link to post
Share on other sites
It's not at all certain that the data you receive is a full message, or that it is zero terminated. Further, sending on a socket is not necessarily guaranteed to send all the data in one go -- you may need to remember outgoing queued data on a per-client basis.

Share this post


Link to post
Share on other sites
Quote:
Original post by hplus0603
It's not at all certain that the data you receive is a full message, or that it is zero terminated. Further, sending on a socket is not necessarily guaranteed to send all the data in one go -- you may need to remember outgoing queued data on a per-client basis.


So I should add a header to the message letting the server know how long the message is, and only send the message when all of the data has been recieved?

If so, I'm not sure how to go about doing it. Any pointers?
~geKingu

Share this post


Link to post
Share on other sites
Quote:
So I should add a header to the message letting the server know how long the message is?


yes, you should have some kind of way to detect if a message the sender sends have been fully received by the receiver. A header preceding the size of the message is a good idea. There there recipient can tell how big the 'payload' of the message is.

Quote:
and only send the message when all of the data has been recieved?


not necessary. You can just pump messages out if the sender does not need to know when the recipient processes the message. send message A, send message B, send message C... The recipient will be responsible for re-constructing the messages and waiting to receive the full payloads *[1].

if you need some sort of synchronisation (i.e. the server should wait until the client, or all clients received the message before doing something else), you'll need some form of aknowledgement system, where the recipient sends back a reply, saying ('I've received message A', 'I've received message B', ....).

if you prefix your messages with a sequence number in the header (an number that increases by one for each message the server sends), the recipient can just send back the sequence number that identifies the message uniquely.

[1] It's best if you have some sort of caching mechanism, since it is quite possible your recipients will even receive incomplete message headers, let alone incomplete payloads, until the remainder is received through the socket later on.

Same thing should be done if you need your sender to process aknowledgements, since an ack itself (say a 4 byte number) may be also fragmented (i.e. server receive the first three bytes of the ack in one recv(), then the last byte in another recv()).

if you want a 'what packet I send is what packet you receive' system, UDP will do that. However, the datagrams you send through UDP can be.

1) not received at all.
2) out of order.
3) duplicated.

[Edited by - oliii on December 18, 2008 12:57:10 PM]

Share this post


Link to post
Share on other sites
Thanks for the reply oliii.

What I've done is created a buffer on the client side reach recieves each packet from the server individually, but only prints the message once it's been recieved entirely. The first byte send denotes the length of the message to be receieved, and it's been working fine so far :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this