以线程实现TCP并发服务器

对服务器来说,以线程为客户服务的方式有三种:

1.每来一个客户就为其创建一个线程;

2.创建一个线程池,在线程中accept;

3.创建一个线程池,在main中accept;

对于第一种:

int  main(int argc, char const *argv[])
{
	int listenfd,connfd;
	void sig_int(int);
	void *doit(void *);
	pthread_t tid;
	socklen_t clilen,addrlen;
	struct sockaddr *cliaddr;

	listenfd = /*创建一个监听套接字*/
	cliaddr = malloc(addrlen);
	signal(SIGINT,sig_int);
	for(;;)
	{
		connfd = accept(listenfd,cliaddr,&clilen);
		pthread_create(&tid,NULL,&doit,(void *) connfd);
	}
	return 0;
}

void *doit(void *arg)
{
	void web_child(int);
	pthread_detach(pthread_self());
	web_child((int) arg);//对套接字进行处理
	close((int) arg);
	return NULL:
}

对于第二种:

typedef struct 
{
	pthread_t thread_tid;
	long thread_count;
}THread;
THread *tptr;

int listenfd,nthreads;
socklen_t addrlen;
pthread_mutex_t mlock;

int main(int argc, char const *argv[])
{
	int i;
	void sig_int(int,thread_make(int));
	listenfd = tcp_listen(/**/);
	nthreads = atoi(argv[argc-1]);
	tptr = calloc(nthreads,sizeof(THread));//一共nthreads个线程,线程信息用结构体数组来保存

	for(i=0;i<nthreads;i++)
		thread_make(i);//提前创建一个线程池
	signal(SIGINT,sig_int);
	for(;;)
		pause();
}

void thread_make(int i)
{
	void *thread_main(void *);
	pthread_create(&tptr[i].thread_tid,NULL,&thread_main,(void *) i);
	return;
}

void *thread_main(void *arg)
{ 
    int connfd;
    void web_child(int);
    socklen_t clilen;
    struct sockaddr *cliaddr;
    cliaddr = malloc(addrlen);

    for(;;)
    {
    	clilen = addrlen;
    	/*先抢到锁的线程,先accept,这样保证每次只有一个线程处理新到来的连接;
    	这里不用互斥锁也是可以的,但是每个线程都会阻塞在accept中,当有一个客户到来时,就会引发惊群问题(所有线程被唤醒,但只有一个线程为客户服务)*/
    	pthread_mutex_lock(&mlock);
    	connfd = accept(listenfd,cliaddr,&clilen);
    	pthread_mutex_unlock(&mlock);
    	tptr[(int) arg].thread_count++;

    	web_child(connfd);
    	close(connfd);
    }
}

对于第三种:


typedef struct 
{
	pthread_t thread_tid;
	long thread_count;
}THread;
THread *tptr;

#define MAXNCLI 32
int clifd[MAXNCLI] ,iget ,iput;
pthread_mutex_t clifd_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t clifd_cond = PTHREAD_COND_INITIALIZER;

static int nthreads;

int main(int argc, char const *argv[])
{
	int i;
	int connfd;
	socklen_t clilen;
	struct sockaddr *cliaddr;
	void sig_int(int,thread_make(int));
	listenfd = tcp_listen(/**/);
	nthreads = atoi(argv[argc-1]);
	cliaddr = malloc(addrlen);
	tptr = calloc(nthreads,sizeof(THread));//一共nthreads个线程,线程信息用结构体数组来保存
    iget=iput=0;

	for(i=0;i<nthreads;i++)
		thread_make(i);//提前创建一个线程池
	signal(SIGINT,sig_int);
	for(;;)
	{
		clilen = addrlen;
		connfd = accept(listenfd,cliaddr,&clilen);//在main里accept,然后把accept返回的套接字保存起来,分配一个线程为其服务
		pthread_mutex_lock(&clifd_mutex);
		clifd[iput] = connfd;
		if(++iput == MAXNCLI)
			iput = 0;
		pthread_cond_signal(&clifd_cond);
		pthread_mutex_unlock(&clifd_mutex);

	}
}

void thread_make(int i)
{
	void *thread_main(void *);
	pthread_create(&tptr[i].thread_tid,NULL,&thread_main,(void *) i);
	return;
}

void *thread_main(void *arg)
{ 
    int connfd;
    void web_child(int);
    
    for(;;)
    {
    	pthread_mutex_lock(&clifd_mutex);
    	while(iget == iput)
    		pthread_cond_wait(&clifd_cond,&clifd_mutex);//进入pthread_cond_wait,就会释放clifd_mutex,返回就重新加锁
    	connfd = clifd[iget];
    	if(++iget == MAXNCLI)
    		iget = 0;
    	pthread_mutex_unlock(&clifd_mutex);
    	tptr[(int) arg].thread_count++;
    	web_child(connfd);
    	close(connfd);
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值