UNIX网络编程——常用服务器模型总结
下面有9种服务器模型分别是:
- 迭代服务器。
- 并发服务器,为每个客户fork一个进程。
- 预先派生子进程,每个子进程都调用accept,accept无上锁保护。
- 预先派生子进程,以文件锁的方式保护accept。
- 预先派生子进程,以线程互斥锁上锁的方式保护accept。
- 预先派生子进程,由父进程向子进程传递套接口描述字。
- 并发服务器,为每个客户请求创建一个线程。
- 预先创建线程,以互斥锁上锁方式保护accept。
- 预先创建线程,由主线程调用accept,并把每个客户连接传递给线程池中某个可用线程。
1、迭代服务器
socket
bind
listen
for(;;)
{
connfd = accept(listenfd, (SA*)&cliaddr, &clilen);
process_connection(connfd);
close(connfd);
}
init_address(server_addr)
listenfd = socket(AF_INET,SOCKET_STREAM,0);
bind(listenfd, (SA*)server_addr, sizeof(serveraddr));
listen(listenfd,BACKLOG);
for(;;)
{
connfd = accept(listenfd, (SA*)&cliaddr, &clilen);
if(connfd < 0)
{
if(EINTR == errno)
continue;
else
//error
} if(fork() == 0)
{
close(c=listenfd);
process_connection(connfd); //child process
exit(0);
}
close(connfd);//parent, close connected socket
}
- 服务器必须在启动的时候判断需要预先派生多少子进程
- 惊群现象(一个连接到来唤醒所有监听进程),不过较新版本的linux貌似修正了这个问题
static pthread_mutex_t *mptr;
void
my_lock_init(char *pathname)
{
int fd;
pthread_mutexattr_t mattr;
//因为是相关进程所以可以使用/dev/zero设备创建共享内存
//优势是调用mmap创建共享存储区之前无需一个实际的文件
//映射/dev/zero自动创建一个指定长度的映射区
fd = open("/dev/zero", O_RDWR, 0,);
// 将mptr映射到共享存储区
mptr = mmap(0, sizeof(pthread_mutex_t), PORT_READ | PORT_WRITE, MAP_SHARED, fd, 0);
close(fd);
pthread_mutexattr_init(&mattr);
pthread_mutexattr_setpshared(&mptr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(mptr, &mattr);
} void
my_lock_wait()
{
pthread_mutex_lock(mptr);
} void
my_lock_release()
{
pthread_mutex_unlock(mptr);
} int
main(int argc, char **argv)
{
//init socket and address
my_lock_init(pathname);
for(i = 0; i < nchildren; ++i)
{
pids[i] = child_make(i, listenfd, addrlen);
} for(;;)
pause();
} pid_t
child_make(int i, int listenfd, int addrlen)
{
pid_t pid; if((pid = fork) > 0)
return pid; child_main(i, listenfd, addrlen);
} void
child_main()
{
for(;;)
{
my_lock_wait();
connfd = accept(listenfd, chiladdr, &clilen);
my_lock_release();
web_child(connfd);
close(connfd);
}
}
- 编码复杂—父进程必须跟踪子进程的忙闲状态,以便给空闲子进程传递新的套接口。在前述的预先派生子进程的例子中,父进程无需关心由哪一个子进程接收一个客户连接,操作系统会根据调度算法处理这些细节。采用这种模型的结果是这些进程无法均衡的处理连接。
- 父进程通过字节流管道把描述子传递到各个子进程,并且各个子进程通过字节流管道写回单个字节,比起无论是使用共享内存区中的互斥锁还是使用文件锁实施的上锁和解锁都更费时。
for(;;)
{
connfd = accept(listenfd, cliaddr, &clilen,);
pthread_create(&tid, NULL, &doit, (void *)connfd);
} void *
doit(void *arg)
{
pthread_detach(pthread_self());
web_child((int)arg);
close((int)arg)
return (NULL);
}
- 编程简介,易于理解
- 线程池的方式避免了现场创建线程的开销
- OS线程调度算法保证了线程负载的均衡性
UNIX网络编程——常用服务器模型总结的更多相关文章
- UNIX环境高级编程——TCP/IP网络编程 常用网络信息检索函数
UNIX环境高级编程——TCP/IP网络编程 常用网络信息检索函数 gethostname() getppername() getsockname() gethostbyname() ...
- UNIX网络编程——并发服务器(TCP)
在迭代服务器中,服务器只能处理一个客户端的请求,如何同时服务多个客户端呢?在未讲到select/poll/epoll等高级IO之前,比较老土的办法是使用fork来实现. 网络服务器通常用fork来同时 ...
- UNIX网络编程——getsockname和getpeername函数
UNIX网络编程--getsockname和getpeername函数 来源:网络转载 http://www.educity.cn/linux/1241293.html 这两个函数或者 ...
- 【LINUX/UNIX网络编程】之简单多线程服务器(多人群聊系统)
RT,Linux下使用c实现的多线程服务器.这个真是简单的不能再简单的了,有写的不好的地方,还希望大神轻拍.(>﹏<) 本学期Linux.unix网络编程的第四个作业. 先上实验要求: [ ...
- 【LINUX/UNIX网络编程】之使用消息队列,信号量和命名管道实现的多进程服务器(多人群聊系统)
RT,使用消息队列,信号量和命名管道实现的多人群聊系统. 本学期Linux.unix网络编程的第三个作业. 先上实验要求: 实验三 多进程服务器 [实验目的] 1.熟练掌握进程的创建与终止方法: 2 ...
- 【Linux/unix网络编程】之使用socket进行TCP编程
实验一 TCP数据发送与接收 [实验目的] 1.熟练掌握套接字函数的使用方法. 2.应用套接字函数完成基本TCP通讯,实现服务器与客户端的信息交互. [实验学时] 4学时 [实验内容] 实现一个服务器 ...
- Unix网络编程--卷二:进程间通信
Unix网络编程--卷二:进程间通信 本书是一部Unix网络编程的经典之作!进程间通信(IPC)几乎是所有Unix程序性能的关键,理解IPC也是理解如何开发不同主机网络应用程序的必要条件.本书从对Po ...
- Unix网络编程--卷一:套接字联网API
UNIX网络编程--卷一:套接字联网API 本书面对的读者是那些希望自己编写的程序能够使用成为套接字(socket)的API进行彼此通信的人. 目录: 0.准备环境 1.简介 2.传输层:TCP.UD ...
- [转载] 读《UNIX网络编程 卷1:套接字联网API》
原文: http://cstdlib.com/tech/2014/10/09/read-unix-network-programming-1/ 文章写的很清楚, 适合初学者 最近看了<UNIX网 ...
随机推荐
- bzoj3702二叉树 线段树合并
3702: 二叉树 Time Limit: 15 Sec Memory Limit: 256 MBSubmit: 600 Solved: 272[Submit][Status][Discuss] ...
- Mybatis迷你版--QueryObjectFactory
今天在看JDBC4.2新规范,然后无意之间就碰到了这个东西QueryObjectFactory, 市面上orm框架有很多,在这里我就不一一列举了.那么今天我来记录一下QueryObjectFactor ...
- SQL_SERVER_2008升级SQL_SERVER_2008_R2的方法
SQL 2008升级到SQL 2008 R2. 说到为什么要升级是因为,从另一台机器上备份了一个数据库,到我的机器上还原的时候提示"948错误,意思就是不能把高版本的数据库附加到低版本上,所 ...
- jquery 跨域请求数据问题
昨天参加了一个前端的面试,被问到一个跨域请求数据问题,我们之前一直用的是apicloud的api进行请求的,跨域是被apicloud封装起来的,也就没有注意跨域请求数据的问题.当被问到用jquery跨 ...
- 在confluence中出现Handshake failed due to invalid Upgrade header: null
在confluence中出现Handshake failed due to invalid Upgrade header: null 昨天晚上同事说confluence写完日志保存不了,然后我登陆co ...
- Lintcode392 Is Subsequence solution 题解
[题目描述] Given a string s and a string t, check if s is subsequence of t. You may assume that there is ...
- 单页应用动态设置页面title
1.适用场景:所有通过router路由的单页应用. 2.示例代码:本文以vue-router为例. 在router.js中: let router = new Router({ routes: [ { ...
- SpringBoot+Mybatis+ Druid+PageHelper 实现多数据源并分页
前言 本篇文章主要讲述的是SpringBoot整合Mybatis.Druid和PageHelper 并实现多数据源和分页.其中SpringBoot整合Mybatis这块,在之前的的一篇文章中已经讲述了 ...
- JAVA反射之Class类的练习
package zhang; /** * JAVA反射之CLass类的练习 * * 在面向对象的语言里,万事万物皆对象,那么类是谁的对象呢? * 类的类型是CLass * * */ class Tes ...
- MySQL DELETE 语句
MySQL DELETE 语句 你可以使用 SQL 的 DELETE FROM 命令来删除 MySQL 数据表中的记录. 你可以在mysql>命令提示符或PHP脚本中执行该命令. 语法 以下是S ...