PDA

View Full Version : Server seems to make a Pause and drinks coffee


nick
04-10-2003, 02:54 PM
Hi board,

following part of my code from a chatserver do some strange things.

The Server is runnig about 2 hours without problems (with 1 - 200 Users), but sometimes the server stopps accepting connections, recv and sending messages. The process ist still runnig, after +-15min and reconnect of all users the server works like before.

Do someone have an idea or a hint?
Thanks in advance and sorry for my english.

UPDATED : 16-04-2003

int main(void)
{
struct sockaddr_in myaddr; // server address
struct sockaddr_in remoteaddr; // client address
int listener; // listening socket descriptor
int newfd = 0; // newly accept()ed socket descriptor
int nbytes;
int ssoval=1; // for setsockopt() SO_REUSEADDR, below
int i;

fd_set master; // master file descriptor list
fd_set read_fds; // temp file descriptor list for select()

socklen_t addrlen;

signal(SIGPIPE, SIG_IGN); // 0.0.6 - Ignoriert Broken Pipe Ausstieg
signal(SIGCLD, SIG_IGN);

LoadCfg("server.cfg");

FD_ZERO(&master); // clear the master and temp sets
FD_ZERO(&read_fds);

// get the listener
if ((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}


/* Set socket to non-blocking */
int flags;

if ((flags = fcntl(listener, F_GETFL, 0)) < 0) {
close(listener);
printf("error getting flags on socket; %i\n", listener);
}

if ((fcntl(listener, F_SETFL, flags | O_NONBLOCK, 0)) < 0) {
close(listener);
printf("error setting socket to non-blocking; %i\n", listener);
}


// bind Port
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = INADDR_ANY;
myaddr.sin_port = htons(CK_port);
memset(&(myaddr.sin_zero), '\0', 8);


// 0.1.1
ssoval = 1;
if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (char *)&ssoval, sizeof(ssoval))<0) {
perror("setsockopt");
exit(1);
}
ssoval = 0;
if (setsockopt(listener, SOL_SOCKET, SO_KEEPALIVE, (char *)&ssoval, sizeof(ssoval))<0) {
perror("setsockopt");
exit(1);
}
// 0.1.1




if (bind(listener, (struct sockaddr *)&myaddr, sizeof(myaddr)) == -1) {
perror("bind");
exit(1);
}

// listen
if (listen(listener, 5) == -1) {
perror("listen");
exit(1);
}

// add the listener to the master set
FD_SET(listener, &master);

// keep track of the biggest file descriptor
fdmax = listener; // so far, it's this one

// Server Startup Screen
init ();

// main loop
for(;;) {
int bufsize = 1023; /* 1K buffer */
char buf[1024] = " ";

read_fds = master; // copy it

if (select(fdmax+1, &read_fds, (fd_set *)0, (fd_set *)0, (struct timeval *) 0) == -1) {
perror("select");
exit(1);
}

// run through the existing connections looking for data to read
for(i = 0; i <= fdmax; i++) {
if (FD_ISSET(i, &read_fds)) { // we got one!!
if (i == listener) {
// handle new connections
addrlen = sizeof(remoteaddr);
if ((newfd = accept(listener, (struct sockaddr *)&remoteaddr, &addrlen)) == -1) {
perror("accept");
} else {
FD_SET(newfd, &master); // add to master set
if (newfd > fdmax) { // erhoeht maximum fd
fdmax = newfd;
}
printf("\n******* [NEW CLIENT FROM %s ON FD %d]\n", inet_ntoa(remoteaddr.sin_addr), newfd);
}
} else {
// handle data from a client
if ((nbytes = recv(i, buf, bufsize, 0)) <= 0) {
if (nbytes == 0) {
printf("SELEC : socket %d hung up\n", i);
} else {
perror("recv");
}
remove_Client(i);
close(i); // close socket - bye bye!
FD_CLR(i, &master); // remove from master set
} else {
buf[nbytes] = '\0'; // null terminate string
printf("RECV< : fd(%i), strlen_buf(%i), bufsize(%i), nbytes(%i)\n", newfd, strlen(buf), bufsize, nbytes);

char *sessid = Regex("^GET /(.*) HTTP", buf);

if (sessid != " ") {
char login[256] = "";

char heute[1024] = "";
struct tm * tm1;
time_t caltime;
caltime = time(NULL);
tm1 = localtime(&caltime);
strftime(heute, 1024, "%H:%M", tm1);

Update_userdata(i, sessid);
Send_Header(i);
sprintf(login, "1140900009CHATMSG|%s||%s|<i>*** %s <b>%s</b> hat den Chat betreten</i><br>",
user[i].sessid, user[i].room, heute, user[i].nick);
printf("%s\n", login); // DEBUG
handleMessage(i, login);
}

if ((Regex("^1140900009CHATMSG(.*)", buf)) != " ") {
handleMessage(i, buf);
}

if ((Regex("^1140900009ADDIGNORE(.*)", buf)) != " ") {
Add_Ignore(i, buf);
}
} // recv end
}
}
} // fd run
} // loop end
return 0;
} // main end

RobSeace
04-10-2003, 07:50 PM
I'm not sure if this is related, but one problem I see is that you don't
null-terminate your buffer after recv(), yet you treat it like it is
null-terminated (you do a strlen() on it)... You need to do
"buf[nbytes] = '\0';" somewhere just after your recv()... But, then,
you'll also need to either increase the size of your buffer by 1 or
decrease the "bufsize" value you pass to recv() by 1, so you always
have room for the null char, even when reading a full buffer's worth...
And, I'm not sure why you're bothering with that "write_fds" set, since
you don't seem to use it at all...

mlampkin
04-12-2003, 02:24 AM
If only you could design it to pause and MAKE coffee... you could make millions from it...

:-/

nick
04-14-2003, 01:26 PM
ha!

x33
04-15-2003, 07:26 AM
Check it out. Linux boxes CAN make coffee. ;)
http://en.tldp.org/HOWTO/mini/Coffee.html

nick
04-15-2003, 02:28 PM
Yeah, that's a promisingly great project.
Specially the "Overdose symptoms" are nice ;)

x33
04-15-2003, 03:06 PM
Ha-ha! =)...
I wonder what happens to the produced coffee when there's a 'kernel panic'... =)))

nick
04-15-2003, 05:21 PM
i think a backup machine will initialize an "make extra strong coffee" function for an extra long night then.

By the way: Now I got a resolution for my Problem (this was actual reason for this Topic) but talking about making coffee makes more fun.

it seems that linger solve this problem.


ssoval = 0;
mLinger.l_onoff = 1;
mLinger.l_linger = 30;
if (setsockopt(listener, SOL_SOCKET, SO_LINGER, (char *)&mLinger, sizeof(mLinger))<0) {
perror("setsockopt");
exit(1);
}
if (setsockopt(listener, SOL_SOCKET, SO_KEEPALIVE, (char *)&ssoval, sizeof(ssoval))<0) {
perror("setsockopt");
exit(1);
}

x33
04-15-2003, 06:07 PM
But did you find out why your server used to stop for a while?

nick
04-16-2003, 11:27 AM
No this has solved another Problem. The server still stop working by some reasons, specially on higher load. Maybe it's a Socket handling Problem.

(I have reposted the updated Code in the first Topic message)

emihaly
04-16-2003, 11:34 AM
you are out of free descriptor! standard system have 1024. increase it to 8096 is nice. But linger is hard option. Like break window on shop, becose you dont want wait to open hours.

nick
04-16-2003, 11:38 AM
good idea, but this happes even if 50 Users connected. descriptor limit is not reached.

emihaly
04-16-2003, 12:22 PM
maybe all in wait_state???

simple print error code on accept to file to see why it not accept more connection.

p.s make -1 check!

x=accept.....
if(x > -1)
{

// hura work
}
else
{
printf("%d",errorcode.....
}

RobSeace
04-16-2003, 01:40 PM
One thing I now see in your updated code is that you're improperly
referencing "newfd" in a few spots where you should reference "i"
instead... Eg:


if ((Regex("^1140900009CHATMSG(.*)", buf)) != " ") {
handleMessage(newfd, buf);
}

if ((Regex("^1140900009ADDIGNORE(.*)", buf)) != " ") {
Add_Ignore(newfd, buf);
}


Both of those should be "i", I think, since "newfd" isn't even set to
anything useful at that point; it's only set when a new client is accepted...
Also, you're performing a shutdown() after close(), which won't work...
Once you close(), the FD is completely unusable... You could move it to
before the close(), if you wanted, but I don't really see the point of
doing the shutdown() if you're just going to close(), anyway...

I also don't understand why you want to set SO_LINGER... As you have
it coded now, your close()'s could take upto 30 seconds to complete,
before returning to you... Are you sure this isn't the source of your
mysterious stoppages?? There's rarely ever any need to set SO_LINGER,
I find... It's best to let your close()'s return immediately, and let the OS
handle all the flushing and connection termination in the background...
About the only use I've seen for SO_LINGER is to set the linger time to 0,
to force your close()'s to send RSTs instead of FINs... But, even that is
a pretty dodgy use, and not particularly recommended...

nick
04-16-2003, 02:02 PM
You're right i dont need to shutdown() and linger.
I've removed it, but the problem is still there.

After Debuggin i found a possible reason:
The messagewindow of the clients will directly connect to "http://domain:port" to the chatserver and remain open. If i do this 5 times with different browser windows the server will accept it. But after that 5 times the Problem occures, there is no error in serverlog or something. The messagewindow remain white and try to connect endlessly.

I looks like that the listener descriptors aint't free after accepting connections.