Jump to content
  • Advertisement
Sign in to follow this  
cherryhouse

sending... sending... stop.

This topic is 4565 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'm having a problem with my tcp server which seems to be having a problem receiving/sending data after the clients send a bunch of messages at once. Well actually, the messages can be pretty spread apart, but the server still seems to "lockup" until the user who was causing the mass packet, gets kicked or leaves the server. I know tcp is "special" for receiving everysingle packet, and wont move on until all packets have been received, but is there anyway I could speed the speed of the server so it doesn't take so long to receive, process data, then send to the clients again? The server is used almost continuously and will most likely be flooded like this if I use it in a real situation if I put it out for people to use at the point it's at. Perhaps a message queue would be the best situation in this case? Is there any nice solutions that I could be pointed towards, since I'm not exactly sure what I'm looking for at this point? Thanks in advanced. EDIT: I was just thinking, if I used separate sockets for sending and receiving data, would that reduce the "intensity" of this problem? currently, I have one socket(sockfd) to send data and receive data. [Edited by - cherryhouse on April 16, 2006 10:43:55 PM]

Share this post


Link to post
Share on other sites
Advertisement
Guest Anonymous Poster
Are you using blocking sockets? If so, are you using the select() mechanism to ensure that data is waiting on the socket you are calling recv() on?

It sounds to me that what you are experiencing may not be a flooding problem.

A blocking socket will sit there in the recv() function until it gets some data to return. If there is no data there, it will sit in that function until someone sends something.

Either use nonblocking sockets, or use the select() function to determine which sockets have data waiting, and only call recv() on those sockets.

Share this post


Link to post
Share on other sites
Are you using blocking recv() calls? I don't see why sending and receiving should cause each other grief otherwise. I always use separate sockets for separate clients because it fries my brain to think about it otherwise, and it does avoid this sort of thing.

Share this post


Link to post
Share on other sites
I'm using select.

The reason I think the server is flooding is because if a client types
Quote:
hdf
dfjhsd
rehdf
hdfh
dfh
dfhdfsjr
jdfj
dshjfdjhre
hdfjfg
fndf
hredherd
jhdfjg
jrjtrf
j
ghjrdt
jdfj
fgj
djr
tj
fg
d

line breaks being the user pressed enter to send to the server


really quickly, the server doesn't receive anymore messages or send anymore messages until that user leaves(I think I said that already).

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
that small amount of data isn't going to flood your server unless you have teeny tiny buffers and are polling extremely slowly.

In your example, you only have 114 bytes..

I think something is pushing your server into ain infinite loop. Might be your game logic, or might be an issue with a blocking socket.

Can you run your sever through a debugger? when it lockes up pause your debuffer and look at your stack trace. Where in your code did it stop?

perhaps your parser on your server has some bugs in it?

Share this post


Link to post
Share on other sites
you do have a bug somewhere in your code.
I think you should post some code so we can investigate this behavior.

Nuno1

Share this post


Link to post
Share on other sites
This is the code that deals with all the sending and receiving that locks up after a bit

void Server::ServLoop()
{
// Begin loop
for(;;)
{
// Replace slave fd from master fd
slave = master;
// Check sockets for existing data to be read
if (select(fdmax+1, &slave, NULL, NULL, NULL) == -1){
// Check file descriptor and handle messages
Msges.ErrorMsg("Socket selecting failed.");
return;}
// Null all characters in your recv buffer
for(int p = 0; p < 256; p++) recvbuf

= '\0';

// Check sockets for activity
for(i = 0; i <= fdmax; i++)
{
// Check to see if the file descriptor is in the set
if (FD_ISSET(i, &slave))
// If listener receives data from socket i...
if (i == listener)
{
// Accept client attempting to connect
Accept_client();
} else {
// Receive message or remove client from server
Recv_msg();
}
}
}
}

// Accept a client into the server
void Server::Accept_client()
{
// Copy remote_address bytes to addrlen
addrlen = sizeof(remote_address);
// Accept connecting client from listener socket
if ((newfd = accept(listener,
(sockaddr *) &remote_address,
&addrlen)) == -1)
// Output error message if accept fails
{ Msges.ErrorMsg("Accept failed.");
} else {
// If client accept goes successful, add client socket to set
FD_SET(newfd, &master);
// Set max fd to newfd(max user)
if (newfd > fdmax) { fdmax = newfd; }
// Set user ip address in vector
tempuser.ip = inet_ntoa(remote_address.sin_addr);
// Receive client username
recv(newfd, recvbuf, 15, 0);
// Set client username in vector
tempuser.name = recvbuf;
// Set client socket
tempuser.id = newfd;
// Add client to vector
my_vec.push_back(tempuser);
// Output user join message and socket connected on
Msges.JoinMsg(tempuser.name, newfd);
}
}

// Receive a message from a client
void Server::Recv_msg()
{
// Receive buffer on character array recvbuf
if ((bytes = recv(i, recvbuf, 512, 0)) <= 0)
{
// If no data received, remove client from userlist
Remove_client(); // There's no problem with this code
} else {
// If data was received, send to all users
Send_msg();

}
}

// Send a message to (a) client(s)
void Server::Send_msg()
{
// Loop through vector and send message to all users
for(int h = 0; h < my_vec.size(); h++)
{
// Set temporary socket as i
tempuser.id = i;
// Set tempuser2 as temporary vector for comparing
tempuser2 = my_vec.at(h);
// If sockets match, display username of vector position and message
if(tempuser2.id == tempuser.id)
{
strcpy(tempstr, tempuser2.name.c_str());
strcat(tempstr, ": "); strcat(tempstr, recvbuf);
strcpy(recvbuf, tempstr);
}
}

// Loop through all sockets
for(j = 0; j <= fdmax; j++)
{
// if socket j is in the set, send to that socket
if (FD_ISSET(j, &master))
{
// Send recvbuf to all users
send(j, recvbuf, sizeof(recvbuf), 0);
}
}
}

Share this post


Link to post
Share on other sites
I have taken a fast look at your code, the first thing that jump right at me is that you expect to recieve all the message at once.

if ((bytes = recv(i, recvbuf, 512, 0)) <= 0)
{
// If no data received, remove client from userlist
Remove_client(); // There's no problem with this code
} else {
// If data was received, send to all users
Send_msg();

}

TCP work with streams , you should never expect to recieve all of the data in one packet. you should make sure that all of the data has been arrived. for example , you better send the length of the message before the message itself so your application will receive data until the the number of bytes recieved equals to the length.

it also possible to do this while waiting for end-of-line character.

this may put your server in a very strange state and may result with your problem.


write a receive function as I mention and give it a try.

good luck
Nuno1

Share this post


Link to post
Share on other sites
int size;
recv(i, recvbuf, size, 0);
size = atoi (recvbuf);
do{
if ((bytes = recv(i, recvbuf, sizeof(recvbuf), 0)) <= 0)
{
// If no data received, remove client from userlist
Remove_client(); // There's no problem with this code
} else {
// If data was received, send to all users
Send_msg();

}
}while(size > sizeof(recvbuf));


I tried this, didn't quite work out as well as it should have. I sent a bunch of messages and the server didn't stop responding while I was sending them(don't know if I sent enough) but when I would send messages fairly quickly, the size of the buffer would appear in the message once the client received it.

example: user output
Quote:
hello //typing each character every second
h1e1l1l1o //typing "hello" quickly, messages get "mixed" up


Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I'm not sure that you are making the assumption that you get all data as the previous poster asserted. Your check for a socket that has it's FD_ISSET as true but does not return data is a correct check for a disconnected socket.

What seems odd to me is this code:

if (newfd > fdmax) { fdmax = newfd; }
// Set user ip address in vector
tempuser.ip = inet_ntoa(remote_address.sin_addr);
// Receive client username
recv(newfd, recvbuf, 15, 0);
// Set client username in vector
tempuser.name = recvbuf;
// Set client socket
tempuser.id = newfd;
// Add client to vector
my_vec.push_back(tempuser);
// Output user join message and socket connected on
Msges.JoinMsg(tempuser.name, newfd);
}

This code will block on recv(), although it only happens on accept.. so probably not your problem.

You also cannot assume your fd's will be consecutive integers, instead of doing loops from 0 to fd_max, I would cycle through the list of fds you have accepted (looks like the .id member of the structures in your vector)

You are sending to the other clients the contents of your entire recieve buffer. You should only send the amount of data you have recieved, not sizeof(recvbuffer)

Also, your select function will block until it recieves data, unless you set the last parameter to a non-null value.


Ok.. this may be the culprit:


for(int p = 0; p <

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.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!