zoukankan      html  css  js  c++  java
  • UNIX网络编程——客户/服务器程序设计示范(七)

        TCP预先创建线程服务器程序,每个线程各自accept

     

           前面讨论过预先派生一个子进程池快于为每个客户线程派生一个子进程。在支持线程的系统上,我们有理由预期在服务器启动阶段预先创建一个线程池以取代为每个客户线程创建一个线程的做法有类似的性能加速。本服务器的基本设计是预先创建一个线程池,并让每个线程各自调用accept。取代让每个线程都阻塞在accept调用之中的做法,我们改用互斥锁以保证任何时刻只有一个线程在调用accept。这里没有理由使用文件锁保护各个线程中的accept调用,因为对于单个进程中的多个线程,我们总可以使用互斥锁达到同样目的。

    typedef struct {
      pthread_t		thread_tid;		/* thread ID */
      long			thread_count;	/* # connections handled */
    } Thread;
    Thread	*tptr;		/* array of Thread structures; calloc'ed */
    
    int				listenfd, nthreads;
    socklen_t		addrlen;
    pthread_mutex_t	mlock;
    
    #include	"unpthread.h"
    #include	"pthread07.h"
    
    pthread_mutex_t	mlock = PTHREAD_MUTEX_INITIALIZER;
    
    int
    main(int argc, char **argv)
    {
    	int		i;
    	void	sig_int(int), thread_make(int);
    
    	if (argc == 3)
    		listenfd = Tcp_listen(NULL, argv[1], &addrlen);
    	else if (argc == 4)
    		listenfd = Tcp_listen(argv[1], argv[2], &addrlen);
    	else
    		err_quit("usage: serv07 [ <host> ] <port#> <#threads>");
    	nthreads = atoi(argv[argc-1]);
    	tptr = Calloc(nthreads, sizeof(Thread));
    
    	for (i = 0; i < nthreads; i++)
    		thread_make(i);			/* only main thread returns */
    
    	Signal(SIGINT, sig_int);
    
    	for ( ; ; )
    		pause();	/* everything done by threads */
    }
    void
    sig_int(int signo)
    {
    	int		i;
    	void	pr_cpu_time(void);
    
    	pr_cpu_time();
    
    	for (i = 0; i < nthreads; i++)
    		printf("thread %d, %ld connections
    ", i, tptr[i].thread_count);
    
    	exit(0);
    }
    

    #include	"unpthread.h"
    #include	"pthread07.h"
    
    void
    thread_make(int i)
    {
    	void	*thread_main(void *);
    
    	Pthread_create(&tptr[i].thread_tid, NULL, &thread_main, (void *) i);
    	return;		/* main thread returns */
    }
    
    void *
    thread_main(void *arg)
    {
    	int				connfd;
    	void			web_child(int);
    	socklen_t		clilen;
    	struct sockaddr	*cliaddr;
    
    	cliaddr = Malloc(addrlen);
    
    	printf("thread %d starting
    ", (int) arg);
    	for ( ; ; ) {
    		clilen = addrlen;
        	Pthread_mutex_lock(&mlock);
    		connfd = Accept(listenfd, cliaddr, &clilen);
    		Pthread_mutex_unlock(&mlock);
    		tptr[(int) arg].thread_count++;
    
    		web_child(connfd);		/* process request */
    		Close(connfd);
    	}
    }
    
    创建线程
    09       创建线程并使之执行thread_main函数,该函数的唯一参数是本线程在thread结构数组中的下标。
    26-28      thread_main函数在调用accept前后调用pthread_mutex_lock和pthread_mutex_unlock加以保护。


  • 相关阅读:
    网络信息安全攻防学习平台第7题
    深入理解读写锁ReentrantReadWriteLock
    彻底理解ReentrantLock
    (三)应该了解关于并发相关的概念
    (二)并发编程的优缺点
    Linux Makefile多目录的编写
    libcurl 下载上传
    MFC枚举USB设备碰到的一个疑难,还没解决
    MFC一个令人纠心的错误
    如何为你的App获取用户的反馈和5星级评论
  • 原文地址:https://www.cnblogs.com/hehehaha/p/6332539.html
Copyright © 2011-2022 走看看