본문 바로가기

프로그램언어/C/C++

pthread server 예제

server.c

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

#define BUFSIZE 100

void *clnt_connection( void* args );
void send_message( char* message , int len );
void error_handling( char* message );

int clnt_number = 0;
int clnt_socks[10];
pthread_mutex_t mutx;

int main( int argc , char** argv )
{
 int serv_sock;
 int clnt_sock;
 struct sockaddr_in serv_addr;
 struct sockaddr_in clnt_addr;
 int clnt_addr_size;
 pthread_t thread;

 if( argc != 2 )
 {
  printf( "Usage : %s <port> \n " , argv[0] );
  exit( 1 );
 }

 if( pthread_mutex_init( &mutx , NULL ) )
  error_handling( "mutex init error" );

 serv_sock = socket( PF_INET , SOCK_STREAM , 0 );

 memset( &serv_addr , 0 , sizeof( serv_addr ) );
 serv_addr.sin_family = AF_INET;
 serv_addr.sin_addr.s_addr = htonl( INADDR_ANY );
 serv_addr.sin_port = htons( atoi( argv[1] ) );

 if( bind(serv_sock , ( struct sockaddr* ) &serv_addr , sizeof( serv_addr ) ) == -1 )
  error_handling( "bind() error" );

 if( listen( serv_sock , 5 ) == -1 )
  error_handling( "listen() error" );

 while( 1 )
 {
  clnt_addr_size = sizeof( clnt_addr );
  clnt_sock = accept( serv_sock , (struct sockaddr*) &clnt_addr , &clnt_addr_size );

  pthread_mutex_lock( &mutx );
  clnt_socks[clnt_number++] = clnt_sock;
  pthread_mutex_unlock( &mutx );

  pthread_create( &thread , NULL , clnt_connection , ( void* )clnt_sock );

  printf( "new connection , client ip : %s \n" , inet_ntoa( clnt_addr.sin_addr ) );
 }
 return 0;
}

void *clnt_connection( void *argv )
{
 int clnt_sock = ( int )argv;
 int str_len = 0;
 char message[BUFSIZE];
 int i;

 while( (str_len = read( clnt_sock , message , sizeof( message ) ) ) != 0 )
 {
  send_message( message , str_len );
 }

 pthread_mutex_lock( &mutx );
 for( i = 0; i < clnt_number; ++i )
 {
  if( clnt_sock == clnt_socks[i] )
  {
   for( ; i < clnt_number - 1; ++i )
   {
    clnt_socks[i] = clnt_socks[i+1];
   }
   break;
  }
 }
 clnt_number--;
 pthread_mutex_unlock( &mutx );

 close( clnt_sock );
 return 0;
}

void send_message( char *message , int len )
{
 int i;
 pthread_mutex_lock( &mutx );
 for( i = 0; i < clnt_number; ++i )
 {
  write( clnt_socks[i] , message , len );
 }
 pthread_mutex_unlock( &mutx );
}

void error_handling( char *message )
{
 fputs( message , stderr );
 fputs( '\n' , stderr );
 exit( 1 );
}

 

client.c

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

#define BUFSIZE 100
#define NAMESIZE 20

void *send_message( void *arg );
void *recv_message( void *arg );
void error_handling( char* message );

char name[NAMESIZE] = "[Default]";
char message[BUFSIZE];

int main( int argc , char** argv )
{
 int sock;
 struct sockaddr_in serv_addr;
 pthread_t snd_thread, rcv_thread;
 void *thread_result;

 if( argc != 4 )
 {
  printf( "Usage : %s <IP> <port> <name> \n " , argv[0] );
  exit( 1 );
 }

 sprintf( name , "[%s]" , argv[3] );

 sock = socket( PF_INET , SOCK_STREAM , 0 );
 if( sock == 1 )
  error_handling( "socket() error" );

 memset( &serv_addr , 0 , sizeof( serv_addr ) );
 serv_addr.sin_family = AF_INET;
 serv_addr.sin_addr.s_addr = inet_addr( argv[1] );
 serv_addr.sin_port = htons( atoi( argv[2] ) );

 if( connect( sock , (struct sockaddr*) &serv_addr , sizeof( serv_addr ) ) == -1 )
  error_handling( "bind() error" );

 pthread_create( &snd_thread , NULL , send_message , ( void* ) sock );
 pthread_create( &rcv_thread , NULL , recv_message , ( void* ) sock );

 pthread_join( snd_thread , &thread_result );
 pthread_join( rcv_thread , &thread_result );

 close( sock );
 return 0;
}

void *send_message( void *arg )
{
 int sock = (int)arg;
 char name_message[NAMESIZE+BUFSIZE];
 while( 1 )
 {
  fgets( message , BUFSIZE , stdin );
  if( !strcmp( message , "q\n" ) )
  {
   close( sock );
   exit( 0 );
  }
  sprintf( name_message , "%s %s" , name , message );
  write( sock , name_message , strlen( name_message ) );
 }
}

void *recv_message( void *arg )
{
 int sock = (int)arg;
 char name_message[NAMESIZE+BUFSIZE];
 int str_len;
 while( 1 )
 {
  str_len = read( sock , name_message , NAMESIZE+BUFSIZE-1 );
  if( str_len == -1 )
   return 1;

  name_message[str_len] = 0;
  fputs( name_message , stdout );
 }
}

void error_handling( char *message )
{
 fputs( message , stderr );
 fputs( '\n' , stderr );
 exit( 1 );
}

 

컴파일 실행

[cent@centhost pthread]$ gcc -D_REENTRANT server.c -o server -lpthread

[cent@centhost pthread]$ ./server 9999

 

[cent@centhost pthread]$ gcc -D_REENTRANT client.c -o client -lpthread

[cent@centhost pthread]$ ./client 127.0.0.1 9999 kim

 

[cent@centhost pthread]$ ./client 127.0.0.1 9999 lee

'프로그램언어 > C/C++' 카테고리의 다른 글

Posix Thread Example  (0) 2012.03.24
컴파일 과정 & gcc 옵션 요약  (0) 2012.03.24
Pthread API Reference  (1) 2012.03.24
유용하게 사용하는 매크로 함수  (0) 2012.03.24
[AIX]dynamic library & static library  (0) 2012.03.24