上一篇的介绍已经OK,那么此处就只贴上代码!
CODE_1 : 主线程accept,但是线程比进程有一个好处是,对于conn_fd资源来说是可以直接共享的,所以就可以不需要像在进程中那样需要传递socket,所以设计会简单一点!但是同样注意互斥的问题!
Server:
/*
主线程预先创建一批线程,线程进行等待,然后主线程
accept, 子线程互斥抢占conn_fd,然后处理数据
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/select.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#define PORT 6000
#define MAXBACK 100
#define MAXLINE 1024
#define CHILD_NUM 10
pthread_mutex_t g_mutex; //!> 互斥量
pthread_cond_t g_cond; //!> 条件变量
int connfds[MAXBACK]; //!> 保存连接s
int i_get = 0; //!> 取出connfd
int i_put = 0; //!> 放进去connfd
void * thread_do( void * arg )
{
int i = 0;
int n_read;
int conn_fd;
char buf[MAXLINE];
while( 1 )
{
pthread_mutex_lock( &g_mutex ); //!> 加锁
while( i_get == i_put ) //!> 当前缓冲区没有connfd
{ //!> 阻塞
pthread_cond_wait( &g_cond, &g_mutex );
}
conn_fd = connfds[i_get]; //!> 获取conn_fd
if( ++i_get == MAXBACK ) //!> 到头
{
i_get = 0;
}
pthread_mutex_unlock( &g_mutex ); //!> 解锁
while( strcmp( buf, "Q" ) != 0 && strcmp( buf, "q" ) != 0 )
{
if( ( n_read = read( conn_fd, buf, MAXLINE ) ) < 0 )
{
printf( "Read errnr! :%d \n", errno );
exit( EXIT_FAILURE );
}
else if( n_read == 0 )
{
continue;
}
else
{
while( buf[i] )
{
buf[i] = toupper( buf[i] );
i++;
}
printf("Child %d done! \n", ( int )pthread_self());
printf("Child %d send %s\n", ( int )pthread_self(), buf);
write( conn_fd, buf, strlen( buf ) ); //!> 写回给client
}
}
}
}
//!> MAIN
//!>
int main( int argc, char ** argv )
{
pthread_t tids[CHILD_NUM];
int i;
int listen_fd;
int conn_fd;
int n_read;
char buf[5];
struct sockaddr_in servaddr;
struct sockaddr_in cliaddr;
int len = sizeof( struct sockaddr_in );
//!>下面需要设置互斥
//!>
pthread_mutex_init( &g_mutex, NULL ); //!> 互斥量初始化
pthread_cond_init( &g_cond, NULL ); //!> 条件变量初始化
//!> server 套接口
//!>
bzero( &servaddr, sizeof( servaddr ) );
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl( INADDR_ANY );
servaddr.sin_port = htons( PORT );
//!> 建立套接字
//!>
if( ( listen_fd = socket( AF_INET, SOCK_STREAM, 0 ) ) == -1 )
{
printf("Socket Error...\n" , errno );
exit( EXIT_FAILURE );
}
//!> 绑定
//!>
if( bind( listen_fd, ( struct sockaddr *)&servaddr, sizeof( servaddr ) ) == -1 )
{
printf("Bind Error : %d\n", errno);
exit( EXIT_FAILURE );
}
//!> 监听
//!>
if( listen( listen_fd, MAXBACK ) == -1 )
{
printf("Listen Error : %d\n", errno);
exit( EXIT_FAILURE );
}
for( i = 0; i < CHILD_NUM; i++ ) //!> 创建10个线程
{
if( pthread_create( &tids[i], NULL, thread_do, NULL ) != 0 )
{
printf("Create %d thread error! : %d", i, errno);
exit( EXIT_FAILURE );
}
}
while( 1 )
{
if( ( conn_fd = accept( listen_fd, ( struct sockaddr *)&cliaddr , &len ) ) == -1 )
{
printf("Accept error! :%d\n", errno);
exit( EXIT_FAILURE );
}
pthread_mutex_lock( &g_mutex ); //!> 加锁
connfds[i_put] = conn_fd; //!> 放进缓存区
if( ++i_put == MAXBACK ) //!> 到头
{
i_put = 0;
}
if( i_get == i_put )
{
printf( "Get and put error! :%d\n", errno );
exit( EXIT_FAILURE );
}
pthread_cond_signal( &g_cond ); //!> 给一个信号说明有数据了
pthread_mutex_unlock( &g_mutex ); //!> 解锁
}
pthread_mutex_destroy( &g_mutex ); //!> 删除互斥灯
pthread_cond_destroy( &g_cond );
return 0;
}
Client 和进程中的一样,可以直接copy!
CODE_2 : 直接由子线程accept,还是互斥问题( 这个问题比较简单 )
/*
主线成创建n个子线程,然后主线成就没有事做了,
进入pause,由子线程互斥调用accept处理
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/select.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#define PORT 6000
#define MAXBACK 100
#define MAXLINE 1024
#define CHILD_NUM 10
pthread_mutex_t g_mutex; //!> 互斥量
//!> 子线程子线程执行函数
//!>
void * thread_do( void * arg )
{
struct sockaddr_in cliaddr;
int len = sizeof( struct sockaddr_in );
int conn_fd;
int n_read;
int i;
char buf[MAXLINE];
int *listen_fd = (int *)arg;//!> 监听口号
while( 1 )
{
pthread_mutex_lock( &g_mutex ); //!> 加锁
if( ( conn_fd = accept( *listen_fd, ( struct sockaddr *)&cliaddr , &len ) ) == -1 )
{
printf(" Thread %d accept error! :%d \n", ( int )pthread_self(), errno);
exit( EXIT_FAILURE );
}
pthread_mutex_unlock( &g_mutex );//!> 加锁
while( strcmp( buf, "Q" ) != 0 && strcmp( buf, "q" ) != 0 )
{
memset( buf, 0, sizeof( buf ) );
if( ( n_read = read( conn_fd, buf, MAXLINE ) ) < 0 )
{
printf( "Read errnr! :%d \n", errno );
exit( EXIT_FAILURE );
}
else if( n_read == 0 )
{
continue;
}
else
{
while( buf[i] )
{
buf[i] = toupper( buf[i] );
i++;
}
printf("Child %d done! \n", ( int )pthread_self());
printf("Child %d send %s\n", ( int )pthread_self(), buf);
write( conn_fd, buf, strlen( buf ) ); //!> 写回给client
}
}
}
}
//!> MAIN
//!>
int main( int argc, char ** argv )
{
int i;
int listen_fd;
int conn_fd;
int n_read;
char buf[5];
pthread_t tids[CHILD_NUM];
struct sockaddr_in servaddr;
//!> 互斥锁
//!>
pthread_mutex_init( &g_mutex, NULL ); //!> 互斥量初始化
//!> server 套接口
//!>
bzero( &servaddr, sizeof( servaddr ) );
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl( INADDR_ANY );
servaddr.sin_port = htons( PORT );
//!> 建立套接字
//!>
if( ( listen_fd = socket( AF_INET, SOCK_STREAM, 0 ) ) == -1 )
{
printf("Socket Error...\n" , errno );
exit( EXIT_FAILURE );
}
//!> 绑定
//!>
if( bind( listen_fd, ( struct sockaddr *)&servaddr, sizeof( servaddr ) ) == -1 )
{
printf("Bind Error : %d\n", errno);
exit( EXIT_FAILURE );
}
//!> 监听
//!>
if( listen( listen_fd, MAXBACK ) == -1 )
{
printf("Listen Error : %d\n", errno);
exit( EXIT_FAILURE );
}
for( i = 0; i < CHILD_NUM; i++ ) //!> 创建10个线程
{
if( pthread_create( &tids[i], NULL, thread_do, &listen_fd ) != 0 )
{
printf("Create %d thread error! : %d", i, errno);
exit( EXIT_FAILURE );
}
if( pthread_detach( tids[i] ) != 0 )
{
printf("Thead %d detach error! :%d \n", ( int )pthread_self(), errno);
exit( EXIT_FAILURE );
}
}
while( 1 )
{
pause(); //!> 主进程暂停
}
return 0;
}
到此,全部结束!
bye~~~