TCP server eating up the whole CPU



WANTED:
A TCP server using poll() and a threaded-client to send the messages to
server. Client will send the characters from stdin to server. Server will
show how many bytes it has received.


PROBLEM:
(1) I can't see server printing the number of bytes received.
(2) Server is eating up the whole CPU.

Problem (2) is one my basic habits :( . I have created servers using
select() and poll() many times in last 2 months and almost all the times I
came up with 100% CPU usage.


-------------------- server.c --------------------------
/* Server to handle client logs
*
* VERSION 1.1
*
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <poll.h>

#define SERVER_IP "127.0.0.1"

enum { RECV_SIZE = 1001, WAIT_CONN = 10 };


int main( int argc, char** argv )
{
int sockfd, acceptfd;
int MYPORT, CONN_MAX;
struct sockaddr_in servaddr, cliaddr;
int recv_bytes, clilen;
char recv_buff[RECV_SIZE];


/* FIRST initialize al the arrays */
memset( recv_buff, '\0', RECV_SIZE );



if( argc != 3 )
{
perror("USAGE: ./file NUMBER-OF-CLIENTS PORT");
exit( EXIT_FAILURE );
}
else
{
CONN_MAX = atoi( argv[1] );
MYPORT = atoi( argv[2] );
}

memset( &servaddr, '\0', sizeof(struct sockaddr_in) );
memset( &cliaddr, '\0', sizeof(struct sockaddr_in) );


/* poll() preparation */
struct pollfd clients[CONN_MAX];
int nready, curr_index, max_index;
int i, j; /* variables used for indexing */

/* initialize socket internet structures */
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(MYPORT);
if( inet_pton(AF_INET, SERVER_IP, &servaddr.sin_addr) < 0 )
{
perror("INET_PTON() error");
exit( EXIT_FAILURE );
}

if( (sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0 )
{
perror("SOCKET() error");
exit( EXIT_FAILURE );
}

if( bind(sockfd, (struct sockaddr*)&servaddr, sizeof(struct sockaddr)) < 0 )
{
perror("BIND() error");
exit( EXIT_FAILURE );
}

printf("BIND() done\n");
if( listen(sockfd, WAIT_CONN) < 0 )
{
perror("LISTEN() error");
exit( EXIT_FAILURE );
}


/*poll() initalization */
clients[0].fd = sockfd;
clients[0].events = POLLIN;
curr_index = 0;
max_index = 0;

printf("Entering POLL()'s infinite LOOP\n");

for( ; ; )
{
if( (nready = poll(clients, max_index + 1, -1)) <= 0 )
{
perror("POLL() error");
exit(EXIT_FAILURE);
}

printf("POLL() done\n");
if( clients[0].revents & POLLIN )
{
/* check if we are exceeding the maximum connections */
if( curr_index > CONN_MAX )
{
perror("too many connections");
continue;
}

clilen = sizeof( struct sockaddr_in );
if( (acceptfd = accept(sockfd, (struct sockaddr*)&cliaddr, &clilen)) < 0 )
{
perror("ACCEPT() error");
exit( EXIT_FAILURE );
}

printf("ACCEPTED\n");
for( i=1; i < CONN_MAX; ++i )
{
if( clients[i].fd < 0 )
{
clients[i].fd = acceptfd;
/* FD added, so we don't need to do anything else */
break;
}
}

if( curr_index > max_index )
{
max_index = curr_index;
}

if( --nready <= 0 )
{
continue;
}

} /* finished with checking the readable FDs */


/* check the readbale FDs for data */
for( j = 0; j < max_index; ++j )
{
if( clients[j].fd < 0 )
{
continue;
}

if( clients[j].fd & (POLLIN | POLLERR) )
{
if( (recv_bytes = recv(clients[j].fd, recv_buff, RECV_SIZE, 0)) <= 0 )
{
perror("CLIENT_SIDE problem");
close( clients[i].fd );
clients[j].fd = -1;
}
else
{
printf("I received %d bytes\n", recv_bytes);
continue;
}

if( --nready <= 0 )
{
break; /* no more redable FDs, so break out of this reading data loop */
}

} /* if( POLLIN | POLLERR ) */
} /* for loop for reading data */
} /* for( ; ; ) loop */


return 0;

}


---------------------------- threaded-client.c ---------------------------------
/* A threaded client */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <poll.h>
#include <pthread.h>


#define SERVER_IP "127.0.0.1"

enum { ARRSIZE = 1001 };

static void* thread_send( void * );


int main( int argc, char** argv )
{
int sockfd, MYPORT;
struct sockaddr_in cliaddr;
pthread_t tid;


memset( &cliaddr, '\0', sizeof(struct sockaddr_in) );

if( argc != 2 )
{
perror("USAGE: ./file PORT");
exit( EXIT_FAILURE );
}
else
{
MYPORT = atoi( argv[1] );
}


cliaddr.sin_family = AF_INET;
cliaddr.sin_port = htons( MYPORT );
if( inet_pton(AF_INET, SERVER_IP, &cliaddr.sin_addr) < 0 )
{
perror("INET_PTON() error");
exit( EXIT_FAILURE );
}

if( (sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0 )
{
perror("SOCKET() error");
exit( EXIT_FAILURE );
}


if( connect(sockfd, (struct sockaddr*)&cliaddr, sizeof(struct sockaddr)) < 0 )
{
perror("CONNECT() error");
exit( EXIT_FAILURE );
}


pthread_create( &tid, NULL, &thread_send, (void*) sockfd );
pthread_join( tid, NULL );


return 0;
}



static void* thread_send( void* sockfd )
{
char arrc[ARRSIZE];
int connfd = (int) sockfd;

/* poll preparation */
struct pollfd fd_array[ARRSIZE];
int nready;


memset( arrc, '\0', ARRSIZE );
/* poll() initialization */
fd_array[0].fd = connfd;
fd_array[0].fd = POLLOUT;


for( ; ; )
{
if( (nready = poll(fd_array, 1, -1)) <= 0 )
{
perror("can not POLL()\n");
exit( EXIT_FAILURE );
}


if( fd_array[0].revents & POLLOUT )
{
if( fgets(arrc, ARRSIZE, stdin) )
{
if( send(connfd, arrc, strlen(arrc), 0) < 0 )
{
perror("SEND() error");
exit( EXIT_FAILURE );
}
}
}
}


return (NULL);
}





--
www.lispmachine.wordpress.com
my email is @ the above blog
check the "About Myself" page

.



Relevant Pages

  • echo client using threads
    ... pollwhile client is written using threads. ... server recvs some characters from a client and then echoes the ... int main ... exit(EXIT_FAILURE); ...
    (comp.unix.programmer)
  • echo client/server give problems if array sizes are different
    ... client asks for user input and then sends that line to the server ... void echo_back(int); ... exit(EXIT_FAILURE); ...
    (comp.unix.programmer)
  • sending recv() data to a file
    ... I am creating a server which recvs the data from the client and sends ... int main ... exit(EXIT_FAILURE); ...
    (comp.unix.programmer)
  • Re: Learnign select()
    ... sends some text to server and then server sends back the same text to ... client and then client prints it onto the screen. ... int main ... exit(EXIT_FAILURE); ...
    (comp.unix.programmer)
  • Re: TCP server eating up the whole CPU
    ... int my_recv; ... struct sockaddr_in servaddr, cliaddr; ... memset(&servaddr, '\0', sizeof(servaddr)); ... exit(EXIT_FAILURE); ...
    (comp.unix.programmer)