Linux 服务器设计( 二 )

    上一篇的介绍已经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~~~



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值