TCP server eating up the whole CPU
- From: arnuld <sunrise@xxxxxxxxxxxxxxx>
- Date: Tue, 29 Jul 2008 12:49:45 +0500
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
.
- Follow-Ups:
- Re: TCP server eating up the whole CPU
- From: malc
- Re: TCP server eating up the whole CPU
- From: arnuld
- Re: TCP server eating up the whole CPU
- From: Bin Chen
- Re: TCP server eating up the whole CPU
- Prev by Date: Re: sending recv() data to a file
- Next by Date: Re: TCP server eating up the whole CPU
- Previous by thread: Software Package Free! ... about our Free Software
- Next by thread: Re: TCP server eating up the whole CPU
- Index(es):
Relevant Pages
|