• 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加以保护。


  • 相关阅读:
    树形DP
    区间DP
    洛谷P1462 通往奥格瑞玛的道路
    缓存--Redis
    Flack--SQLAlchemy
    Flask--WTForms
    Flask框架
    通过反射,获取linkedHashMap的最后一个键值对。对map按照值进行排序。
    Comparable和Comparator的使用
    构造函数,构造代码块,静态函数的执行顺序
  • 原文地址:https://www.cnblogs.com/hehehaha/p/6332539.html
Copyright © 2020-2023  润新知