转载:http://www.cnblogs.com/lizhenghn/p/3618986.html

前面两篇文章(参见)分别介绍了循环服务器和简单的并发服务器网络模型,我们已经知道循环服务器模型效率较低,同一时刻只能为一个客户端提供服务,而且对于TCP模型来说,还存在单客户端长久独占与服务器的连接,无法再响应其他连接,对于前面介绍的并发服务器模型是比较简单的,比如由于预先分配了固定进程数目,就导致无法动态调整等问题。在前面我们也提到了对accept函数的处理是区分不同服务器模型的一个重要依据,当然UDP服务器并不需要accept函数,因此本次主要介绍TCP的高级并发模型。按照对accept的不同处理,接下来主要介绍以下几种并发模型:

  1. 单客户端单进程,统一accept :服务器主进程等待客户端连接,一旦有连接到来,就创建一个进程用于响应;
  2. 单客户端单线程,统一accept :服务器主进程等待客户端连接,一旦有连接到来,就创建一个线程用于响应;
  3. 单客户端单线程,各自accept :预先分配多个线程,在每一个线程里都独自等待客户端的连接并响应(注意accept需要互斥访问);

并发模型伪代码

/* 单客户端单进程,统一accept */
/* 服务器主进程 */socket();bind();listen();while(1){accept();fork();//子进程
  }close(); //关闭服务器端套接字/* 服务器子进程1 */  recv();process();send();close();//关闭客户端套接字/* 服务器子进程2(同上) */
..................
/* 单客户端单线程,统一accept */
/* 服务器主进程 */socket();bind();listen();while(1){accept();pthread_create(); //创建响应线程
 }close();//关闭服务器端套接字/* 服务器线程1 */
recv();
process();
send();
close();//关闭客户端套接字
/* 服务器线程2(同上)  */
..................
/* 单客户端单线程,各自accept */
/* 服务器主进程 */socket();bind();listen();pthread_create();//创建多个线程分别等待客户端连接pthread_join();//等待线程结束close();//关闭服务器端套接字/* 服务器线程1 */
mutex_lock()//互斥锁
accept();
mutex_unlock();recv();
process();
send();
close();//客户端套接字
/* 服务器线程2(同上)  */
..................

一个高级并发服务器模型的例子

单客户端单进程,统一accept  server端程序
 1 /* 单客户端单进程,统一accept  --server端程序*/
 2 #include <sys/types.h>
 3 #include <sys/socket.h>
 4 #include <netinet/in.h>
 5 #include <time.h>
 6 #include <string.h>
 7 #include <stdio.h>
 8 #define BUFFLEN 1024
 9 #define SERVER_PORT 12348
10 #define BACKLOG 5
11
12 static void handle_request(int s_c)
13 {
14     time_t now;
15     char buff[BUFFLEN];
16     int n = 0;
17     memset(buff, 0, BUFFLEN);
18     n = recv(s_c, buff, BUFFLEN,0);
19     if(n > 0 && !strncmp(buff, "TIME", 4))
20     {
21         memset(buff, 0, BUFFLEN);
22         now = time(NULL);
23         sprintf(buff, "%24s\r\n",ctime(&now));
24         send(s_c, buff, strlen(buff),0);
25     }
26
27     close(s_c);    /*关闭客户端*/
28 }
29
30 static void handle_connect(int s_s)
31 {
32
33     int s_c;    /*客户端套接字文件描述符*/
34     struct sockaddr_in from;    /*客户端地址*/
35     int len = sizeof(from);
36
37     /*主处理过程*/
38     while(1)
39     {
40         s_c = accept(s_s, (struct sockaddr*)&from, &len);/*接收客户端连接*/
41         if(s_c > 0)/*客户端成功连接,创建进程进行数据处理*/
42         {
43             if(fork() > 0)  /*父进程*/
44             {
45                 close(s_c); /*关闭父进程的客户端连接套接字*/
46             }
47             else
48             {
49                 handle_request(s_c);/*处理连接请求*/
50             }
51         }
52     }
53 }
54
55 int main(int argc, char *argv[])
56 {
57     int s_s;    /*服务器套接字文件描述符*/
58     struct sockaddr_in local;    /*本地地址*/
59
60     /*建立TCP套接字*/
61     s_s = socket(AF_INET, SOCK_STREAM, 0);
62
63     /*初始化地址*/
64     memset(&local, 0, sizeof(local));
65     local.sin_family = AF_INET;/*AF_INET协议族*/
66     local.sin_addr.s_addr = htonl(INADDR_ANY);/*任意本地地址*/
67     local.sin_port = htons(SERVER_PORT);/*服务器端口*/
68
69     /*将套接字文件描述符绑定到本地地址和端口*/
70     int err = bind(s_s, (struct sockaddr*)&local, sizeof(local));
71     err = listen(s_s, BACKLOG);/*侦听*/
72
73     /*处理客户端连接*/
74     handle_connect(s_s);
75
76     close(s_s);
77
78     return 0;
79 }
单客户端单进程,统一accept  server端程序
 1 单客户端单线程,统一accept  server端程序
 2 #include <sys/types.h>
 3 #include <sys/socket.h>
 4 #include <netinet/in.h>
 5 #include <time.h>
 6 #include <string.h>   #include <pthread>
 7 #include <stdio.h>
 8 #define BUFFLEN 1024
 9 #define SERVER_PORT 12348
10 #define BACKLOG 5
11
12 static void *handle_request(void *argv)
13 {
14     int s_c = *((int*)argv);
15     time_t now;
16     char buff[BUFFLEN];
17     int n = 0;
18     memset(buff, 0, BUFFLEN);
19     n = recv(s_c, buff, BUFFLEN,0);
20     if(n > 0 && !strncmp(buff, "TIME", 4))
21     {
22         memset(buff, 0, BUFFLEN);
23         now = time(NULL);
24         sprintf(buff, "%24s\r\n",ctime(&now));
25         send(s_c, buff, strlen(buff),0);
26     }
27
28     close(s_c);    /*关闭客户端*/
29 }
30
31 static void handle_connect(int s_s)
32 {
33     int s_c;    /*客户端套接字文件描述符*/
34     struct sockaddr_in from;    /*客户端地址*/
35     int len = sizeof(from);
36     pthread_t thread_do;
37
38     /*主处理过程*/
39     while(1)
40     {
41         s_c = accept(s_s, (struct sockaddr*)&from, &len);/*接收客户端连接*/
42         if(s_c > 0)/*客户端成功连接,创建线程进行数据处理*/
43         {
44             int err = pthread_create(&thread_do,NULL,handle_request,(void*)&s_c;
45         }
46     }
47 }
48
49 int main(int argc, char *argv[])
50 {
51     int s_s;    /*服务器套接字文件描述符*/
52     struct sockaddr_in local;    /*本地地址*/
53
54     s_s = socket(AF_INET, SOCK_STREAM, 0);/*建立TCP套接字*/
55
56     /*初始化地址*/
57     memset(&local, 0, sizeof(local));
58     local.sin_family = AF_INET;/*AF_INET协议族*/
59     local.sin_addr.s_addr = htonl(INADDR_ANY);/*任意本地地址*/
60     local.sin_port = htons(SERVER_PORT);/*服务器端口*/
61
62     /*将套接字文件描述符绑定到本地地址和端口*/
63     int err = bind(s_s, (struct sockaddr*)&local, sizeof(local));
64     err = listen(s_s, BACKLOG);/*侦听*/
65
66     /*处理客户端连接*/
67     handle_connect(s_s);
68
69     close(s_s);
70
71     return 0;
72 }

单客户端单线程,各自accept --server端程序

/** 单客户端单线程,各自accept --server端程序 */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <pthread>
#define BUFFLEN 1024
#define SERVER_PORT 12348
#define BACKLOG 5
#define CLIENT_NUM 3pthread_mutex_t g_lock = PTHREAD_MUTEX_INTIALIZER;static void *handle_request(void *argv)
{int s_s = *((int*)argv); //服务器端套接字struct sockaddr_in from;    /*客户端地址*/int len = sizeof(from);int s_c = -1; //客户端套接字for( ; ; ){time_t now;        char buff[BUFFLEN];int n = 0;memset(buff, 0, BUFFLEN);pthread_mutex_lock(&g_lock);s_c = accept(s_s,(struct sockaddr*)&from, &len);pthread_mutex_unlock(&g_lock);    n = recv(s_c, buff, BUFFLEN,0);if(n > 0 && !strncmp(buff, "TIME", 4)){memset(buff, 0, BUFFLEN);now = time(NULL);sprintf(buff, "%24s\r\n",ctime(&now));send(s_c, buff, strlen(buff),0);}close(s_c);    /*关闭客户端*/}return NULL;
}static void handle_connect(int s_s)
{    int s_s = s;pthread_t thread_do[CLIENT_NUM];for(int i=0; i<CLIENT_NUM;++i){int err = pthread_create(&thread_do[i],NULL,handle_request,(void*)&s_s;}//等待线程结束for(int i=0; i<CLIENT_NUM;++i)pthread_join(thread_do[i],NULL);
}int main(int argc, char *argv[])
{int s_s;    /*服务器套接字文件描述符*/struct sockaddr_in local;    /*本地地址*/        s_s = socket(AF_INET, SOCK_STREAM, 0);/*建立TCP套接字*//*初始化地址*/memset(&local, 0, sizeof(local));local.sin_family = AF_INET;/*AF_INET协议族*/local.sin_addr.s_addr = htonl(INADDR_ANY);/*任意本地地址*/local.sin_port = htons(SERVER_PORT);/*服务器端口*//*将套接字文件描述符绑定到本地地址和端口*/int err = bind(s_s, (struct sockaddr*)&local, sizeof(local));err = listen(s_s, BACKLOG);/*侦听*/handle_connect(s_s);/*处理客户端连接*/close(s_s);return 0;
}

Linux网络编程服务器模型选择之并发服务器(下)相关推荐

  1. Linux网络编程服务器模型选择之并发服务器(上)

    转载:http://www.cnblogs.com/lizhenghn/p/3617666.html 与循环服务器的串行处理不同,并发服务器对服务请求并发处理.循环服务器只能够一个一个的处理客户端的请 ...

  2. Linux网络编程服务器模型选择之循环服务器

    转载:http://www.cnblogs.com/lizhenghn/p/3617608.html 在网络程序里面,通常都是一个服务器处理多个客户机,为了出个多个客户机的请求,服务器端的程序有不同的 ...

  3. Linux网络编程服务器模型选择之IO复用循环并发服务器

    在前面我们介绍了循环服务器,并发服务器模型.简单的循环服务器每次只能处理一个请求,即处理的请求是串行的,效率过低:并发服务器可以通过创建多个进程或者是线程来并发的处理多个请求.但是当客户端增加时,就需 ...

  4. 第4章 Linux网络编程 22.多进程实现并发服务器、多线程实现并发服务器

    目录 多线程实现并发服务器 多进程实现并发服务器 多线程实现并发服务器 server_thread.c #include <stdio.h> #include <arpa/inet. ...

  5. Linux网络编程基础<多进程并发服务器>

    一.应用场景 最简单的socket示列代码只能一个客户端连接一个服务器,并不支持多个客户端对服务器的连接,为了能让多个客户端进行连接所以需要多进程或者多线程处理 二.思路解析 服务器端的程序是俩个套接 ...

  6. linux网络编程-多线程实现TCP并发服务器

    客户端跟服务端通信流程 服务端流程步骤 socket函数创建监听套接字lfd; bind函数将监听套接字绑定ip和端口: listen函数将服务器设置为被动监听状态,同时创建一条未完成连接队列(没走完 ...

  7. 【Linux网络编程部分----多进程高并发poll模型】

    目录 前言 背景 分析 编写步骤 服务器: 客户端: 服务器端代码 附:文件操作部分 附:目录操作部分 客户端代码 全部代码 头文件部分 服务器全部代码 客户端所有代码 总结: 前言 本文采用  Vi ...

  8. Linux网络编程基础及多线程并发案例

    目录 1.ip:端口  TCP/IP协议 2.socket 头文件  sys/socket.h 3.字节序 4.ip地址转换函数 5.sockaddr和sockaddr_in 6.服务器端基本函数 b ...

  9. Linux网络编程学习笔记

    声明:1.未经过原作者许可,不可用于商业行为:2.本笔记仅用于知识学习,如有侵权,立即删除. 1.学习链接 黑马程序员-Linux网络编程:https://www.bilibili.com/video ...

最新文章

  1. python包引用问题
  2. linux安装 mysql-5.7.25_Linux 系统下安装 mysql5.7.25(glibc版)
  3. 适合于小团队产品迭代的APP测试流程
  4. junit 案例(三)
  5. 2019昆明计算机会议,计算机 | ACSAC 2019等国际会议信息6条
  6. 博弈论 —— python
  7. 终于看到这么贱的星座分析了
  8. (转)ASP.NET 3.5 企业级开发
  9. 浅析javaIO的原理过程
  10. MFC的消息处理模式
  11. 大家总在讲情商,那到底什么是情商?
  12. Windows10中,如何改变鼠标光标(指针)的大小和颜色?
  13. OpenAI的API key获取方法
  14. 互联网企业申请95号 正确落地方案可节省50%费用
  15. 10#Windows注册表的那些事儿
  16. win10一行命令查看所有wifi密码
  17. 一个基于 Docker 的私有云方案
  18. goplus (go+)初识
  19. HTML中拖动消失的球代码,js拖拽360桌面悬浮球代码
  20. Web实现:各种不同的CSS样式示例

热门文章

  1. root无法运行命令解决办法
  2. 泛型(CSDN转载)
  3. CISSP的成长之路(二十一):用户持有凭证
  4. 可以使用计算机解决的问题是什么,1.1 使用计算机解决问题的一般过程教案1
  5. php redis.dll php5.6,在Windows 64位下为PHP5.6.14安装redis扩展
  6. centos7 python3安装numpy_centos 7 下安装numpy、scipy等python包
  7. 服务器怎么禁止iis静态文件,如何禁止IIS缓存静态文件
  8. minio 并发数_c#(asp.net)线程配置总结
  9. linux 进程的执行时间,Linux 获取进程执行时间
  10. 建模步骤_古建设计 | sketchup建模步骤教程(简易入门版)