UNIX网络编程卷1 server程序设计范式8 预先创建线程,由主线程调用accept
本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie
1.程序启动阶段创建一个线程池之后仅仅让主线程调用 accept 并把客户连接传递给池中某个可用线程。
//用于维护关于每一个线程基于信息的 Thread 结构
typedef struct {
pthread_t thread_tid; /* 线程 ID */
long thread_count; /* 处理的连接数 */
} Thread;
Thread *tptr; /* Thread 结构指针,指向一个用 calloc 产生的 Thread结构数组 */ //定义存放已连接套接字描写叙述符的共享数组
#define MAXNCLI 32
int clifd[MAXNCLI], iget, iput;
pthread_mutex_t clifd_mutex;
pthread_cond_t clifd_cond; /* include serv08 */
#include "unpthread.h"
#include "pthread08.h" static int nthreads;
pthread_mutex_t clifd_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t clifd_cond = PTHREAD_COND_INITIALIZER; int
main(int argc, char **argv)
{
int i, listenfd, connfd;
void sig_int(int), thread_make(int);
socklen_t addrlen, clilen;
struct sockaddr *cliaddr; //1.创建监听套接字
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: serv08 [ <host> ] <port#> <#threads>");
cliaddr = Malloc(addrlen); //2.增设一个命令行參数供用户指定预先派生的线程数
nthreads = atoi(argv[argc-1]);
tptr = Calloc(nthreads, sizeof(Thread)); //iput 是主线程将往 clifd 数组中存放的下一个元素的下标
//iget 是线程池中某个线程将从该数组中取出的下一个元素的下标
iget = iput = 0; /* 4create all the threads */
//3.调用 thread_make 创建各个线程
for (i = 0; i < nthreads; i++)
thread_make(i); /* only main thread returns */ //4.设置中断信号 SIGINT 的处理函数
Signal(SIGINT, sig_int); for ( ; ; ) {
clilen = addrlen;
//5.堵塞于 accept 等待用户连接
connfd = Accept(listenfd, cliaddr, &clilen); //由于clifd 数组是全部线程共享的。所以要调用 pthread_mutex_lock 和 pthread_mutex_unlock 加以保护
Pthread_mutex_lock(&clifd_mutex);
clifd[iput] = connfd; //把已连接套接字存入 clifd 数组的下一个元素
if (++iput == MAXNCLI)
iput = 0;
if (iput == iget)
err_quit("iput = iget = %d", iput);
//发送信号到条件变量信号
Pthread_cond_signal(&clifd_cond); Pthread_mutex_unlock(&clifd_mutex);
}
}
/* end serv08 */ //中断信号 SIGINT 处理函数
void
sig_int(int signo)
{
int i;
void pr_cpu_time(void); //调用 pr_cpu_time 统计资源利用统计
//在预先派生子进程的代码中还要先给每一个子进程发送 SIGTERM 信号终止它们再统计。
//这里由于是线程,而子线程与主线程是在同一个地址空间的,当主线程终止时。子线程也会终止。 pr_cpu_time(); for (i = 0; i < nthreads; i++)
printf("thread %d, %ld connections\n", i, tptr[i].thread_count); exit(0);
} void
thread_make(int i)
{
void *thread_main(void *); //创建线程并使之运行 thread_main 函数,该函数的唯一參数是本线程在 Thread 结构数组中的下标
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); printf("thread %d starting\n", (int) arg);
for ( ; ; ) {
//由于clifd 数组是全部线程共享的。所以要调用 pthread_mutex_lock 和 pthread_mutex_unlock 加以保护
Pthread_mutex_lock(&clifd_mutex);
//若两者相等则无事可做,调用 pthread_cond_wait 在睡眠在条件变量上,等待主线程唤醒
while (iget == iput)
Pthread_cond_wait(&clifd_cond, &clifd_mutex);
//得到要处理的套接字描写叙述符
connfd = clifd[iget]; /* connected socket to service */
if (++iget == MAXNCLI)
iget = 0;
Pthread_mutex_unlock(&clifd_mutex);
tptr[(int) arg].thread_count++; //处理客户请求
web_child(connfd); /* process request */
//关闭已连接套接字
Close(connfd);
}
}
UNIX网络编程卷1 server程序设计范式8 预先创建线程,由主线程调用accept的更多相关文章
- UNIX网络编程卷1 server程序设计范式7 预先创建线程,以相互排斥锁上锁方式保护accept
本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.预先创建一个线程池.并让每一个线程各自调用 accept 2.用相互排斥锁代替让每一个线 ...
- UNIX网络编程卷1 server程序设计范式1 并发server,为每一个客户请求fork一个进程
本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.传统并发server调用 fork 派生一个子进程来处理每一个客户 2.传统并发serv ...
- UNIX网络编程卷1 server编程范式0 迭代server
本文senlie原版的.转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.迭代 TCP server总是在全然处理某个客户的请求后才转向下一个客户. 2.从进程控 ...
- [转载] 读《UNIX网络编程 卷1:套接字联网API》
原文: http://cstdlib.com/tech/2014/10/09/read-unix-network-programming-1/ 文章写的很清楚, 适合初学者 最近看了<UNIX网 ...
- UNIX网络编程 卷2:进程间通信
这篇是计算机类的优质预售推荐>>>><UNIX网络编程 卷2:进程间通信(第2版)> UNIX和网络专家W. Richard Stevens的传世之作 编辑推荐 两 ...
- 《UNIX网络编程 卷1》之"学习环境搭建"(CentOS 7)
<UNIX网络编程 卷1>的源码可以从www.unpbook.com下载得到.解压之后的目录为unpv13e. 详细步骤 编译 进入unpv13e目录,按如下步骤编译: ./configu ...
- UNIX网络编程卷1 时间获取程序server TCP 协议相关性
本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie 最初代码: 这是一个简单的时间获取server程序.它和时间获取程序client一道工作. ...
- 《Unix网络编程卷1:套接字联网API》读书笔记
第一部分:简介和TCP/IP 第1章:简介 第2章:传输层:TCP.UDP和SCTP TCP:传输控制协议,复杂.可靠.面向连接协议 UDP:用户数据报协议,简单.不可靠.无连接协议 SCTP:流控制 ...
- UNIX网络编程卷1 - >环境搭建(ubuntu16.04)
学习unp网络编程,树上的例子均存在#include“unp.h”,故需要对环境进行配置. 1.到资源页下载www.unpbook.com 2.解压并将unpv13e移动到相应的文件夹下 (因为我 ...
随机推荐
- 如何选择Android自动化框架的几点拙见
首先由于我自己也是个新手,也是在学习各种框架然后给公司项目选定相应自动化框架,研究移动自动化测试框架也就近段时间而已,所以我只能从我自己今天为止的认知角度给各个框架抒发我自己的拙见,你看是否能从中接纳 ...
- 菜鸟之路——机器学习之线性回归个人理解及Python实现
这一节很简单,都是高中讲过的东西 简单线性回归:y=b0+b1x+ε.b1=(Σ(xi-x–)(yi-y–))/Σ(xi-x–)ˆ2 b0=y--b1x- 其中ε取 为均值为0的正态 ...
- SSM框架 springMVC对静态资源访问的处理
https://my.oschina.net/hnqingping1255/blog/415575 错误信息 [org.springframework.web.servlet.PageNotFound ...
- Lua 语法要点
table 默认键值都是从1开始 table array = { "A", "B" } array2 = array array[] = "D&quo ...
- [Python]Pandas简单入门(转)
本篇文章转自 https://colab.research.google.com/notebooks/mlcc/intro_to_pandas.ipynb?hl=zh-cn#scrollTo=zCOn ...
- Log4j官方文档翻译(四、如何在java中输出日志消息)
我们已经创建来配置文件,本章详细的介绍下如何生成调试信息,并把他们转化成文本文件. 基本的例子 下面就是创建的一个基本的例子: log4j.properties的内容为: log = /usr/hom ...
- BZOJ 3990: [SDOI2015]排序(搜索+剪枝)
[SDOI2015]排序 Description 小A有一个1-2^N的排列A[1..2^N],他希望将A数组从小到大排序,小A可以执行的操作有N种,每种操作最多可以执行一次,对于所有的i(1< ...
- 【bzoj3280】小R的烦恼 费用流
题目描述 小R最近遇上了大麻烦,他的程序设计挂科了.于是他只好找程设老师求情.善良的程设老师答应不挂他,但是要求小R帮助他一起解决一个难题. 问题是这样的,程设老师最近要进行一项邪恶的实验来证明P=N ...
- [luogu1357] 花园 [dp+矩阵快速幂]
题面: 传送门 思路: 把P形花圃记录为0,C形记录为1,那么一段花圃就可以状态压缩成一个整数 那么,我们可以有这样的状压dp: dp[i][S]表示前i个花圃,最后m个的状态为S的情况 如果这是一条 ...
- [usaco jan 09] 气象牛 baric [dp]
题面: 传送门 思路: 题意有点绕,实际上就是给你一个计算规则,让你取最少的元素,通过这个计算方式,得到一个小于指定误差上限的结果 这个规则分为三个部分,这里分别用pre,sum,suf表示 因为给定 ...