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

转载: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;        
}
复制代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384323.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

剑指Offer05. 替换空格

请实现一个函数&#xff0c;把字符串 s 中的每个空格替换成"%20"。 示例 1&#xff1a; 输入&#xff1a;s “We are happy.” 输出&#xff1a;“We%20are%20happy.” class Solution { public:string replaceSpace(string s) {int count0;int lens.size();stri…

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

转载&#xff1a;http://www.cnblogs.com/lizhenghn/p/3619091.html 在前面我们介绍了循环服务器&#xff0c;并发服务器模型。简单的循环服务器每次只能处理一个请求&#xff0c;即处理的请求是串行的&#xff0c;效率过低&#xff1b;并发服务器可以通过创建多个进程或者是线…

数据结构(六)二叉树的遍历(递归非递归方法)

数据结构&#xff08;六&#xff09;二叉树的遍历&#xff08;递归非递归方法&#xff09; 一、递归方法 1.先序遍历 void PreOrder(BiTree T) {visit(T);PreOrder(T->LChild)PreOrder(T->RChild) }2.先序遍历 void PreOrder(BiTree T) {PreOrder(T->LChild)visit…

memcpy/memset函数的c语言实现

转载&#xff1a;http://blog.csdn.net/u011118276/article/details/46742341 1、memcpy 头文件&#xff1a;#include <string.h> 函数原型&#xff1a;void *memcpy(void *dest, const void *src, size_t n) 功能&#xff1a;将指针src指向的内存空间的n个字节复制到des…

计算机网络(一)计算机网络体系

计算机网络&#xff08;一&#xff09;计算机网络体系一、计算机网络概述概念功能组成分类二、体系结构和参考模型ISO/OSI模型物理层网络层传输层会话层表示层应用层OSI参考模型与TCP/IP参考模型OSI参考模型与TCP/IP参考模型不同5层参考模型一、计算机网络概述 概念 计算机网…

计算机网络(二)物理层

计算机网络&#xff08;二&#xff09;物理层一、通信基础物理层接口特性1.机械特性2.电气特性3.功能特性4.规程特性典型的数据通信模型三种通信方式1.单工通信2.半双工通信/双向交替通信3.全双工通信/双向同时通信数据传输方式串行传输并行传输同步传输异步传输二、数据交换方…

计算机网络(三)数据链路层

计算机网络&#xff08;三&#xff09;数据链路层1.基本概念2.功能概述3.组帧字符计数法字符填充法零比特填充法违规编码法4.差错控制检错编码奇偶校验码CRC循环冗余码纠错编码海明码流量控制停止等待协议滑动窗口协议后退N帧协议&#xff08;GBN&#xff09;选择重传协议5.介质…

libevent网络编程例子(1)

转载&#xff1a;http://blog.csdn.net/huangyimo/article/details/46806193 这篇文章介绍下libevent在socket异步编程中的应用。在一些对性能要求较高的网络应用程序中&#xff0c;为了防止程序阻塞在socket I/O操作上造成程序性能的下降&#xff0c;需要使用异步编程&#xf…

计算机网络(四)网络层

计算机网络&#xff08;四&#xff09;网络层一、概述和功能TCP/IP协议栈IP数据报格式IP数据报分片二、ipv4网络地址转换&#xff08;NAT&#xff09;子网划分子网掩码ARP协议&#xff08;地址解析协议&#xff09;DHCP协议ICMP协议二、ipv6ipv4和ipv6的区别IPv6基本地址类型IP…

Linux下基于socket和多线程的聊天室小程序

转载&#xff1a;http://blog.csdn.net/robot__man/article/details/52460733 要求&#xff1a;基于TCP编写&#xff0c;一个聊天室最多100人。 客户端&#xff1a;   1、用户需要登录&#xff0c;登录时只需要输入一个昵称即可无需判断昵称是否重复&#xff08;如果其他功…

操作系统(一)计算机系统概述

操作系统&#xff08;一&#xff09;计算机系统概述一、操作系统的概念二、功能和目标资源的管理者向上层提供服务对硬件的扩展三、操作系统的特征并发共享虚拟异步四、操作系统的发展与分类手工操作阶段批处理阶段单道批处理系统多道批处理系统分时操作系统实时操作系统操作系…

Linux下使用socket传输文件的C语言简单实现

转载&#xff1a;http://blog.csdn.net/ljd_1986413/article/details/7940938 服务器程序和客户端程序应当分别运行在两台计算机上。 在运行服务器端的计算机终端执行&#xff1a;./file_server 在运行客户端的计算终端上执行&#xff1a;./file_client ipaddr_server 然后根…

操作系统(二)进程管理

ui 操作系统&#xff08;二&#xff09;进程管理一、进程程序和进程进程控制块&#xff08;PCB&#xff09;进程的组成进程的特征进程的状态与转换进程状态的转换进程的组织链接方式索引方式进程的控制进程的创建进程的终止进程阻塞进程唤醒进程切换进程通信共享存储消息传递管…

gethostbyname()函数说明

转载&#xff1a;http://www.cnblogs.com/cxz2009/archive/2010/11/19/1881611.html gethostbyname()函数说明——用域名或主机名获取IP地址 包含头文件 #include <netdb.h> #include <sys/socket.h> 函数原型 struct hostent *gethostbyna…

操作系统(三)内存管理

操作系统&#xff08;三&#xff09;内存管理一、程序执行过程装入的三种方式链接的三种方式二、内存管理的概念内存空间的分配与回收连续分配管理方式单一连续分配固定分区分配动态分区分配首次适应算法最佳适应算法最坏适应算法邻近适应算法非连续分配管理方式基本分页存储管…

操作系统(四)文件管理

操作系统&#xff08;四&#xff09;文件管理一、文件系统基础1.文件逻辑结构无结构文件有结构文件2.文件目录文件控制块&#xff08;FCB&#xff09;目录结构单级目录两级目录结构多级目录结构无环图目录结构3.文件保护口令保护加密保护访问控制4.文件共享硬链接软链接5.文件系…

struct stat结构体简介

转载&#xff1a;http://www.cnblogs.com/CSU-PL/archive/2013/06/06/3120757.html 在使用这个结构体和方法时&#xff0c;需要引入&#xff1a; <sys/types.h> <sys/stat.h> struct stat这个结构体是用来描述一个linux系统文件系统中的文件属性的结构。 可以有两种…

如何在Ubuntu上安装GCC编译器

如何在Ubuntu上安装GCC编译器1.首先更新包列表sudo apt update2.安装build-essential软件包&#xff1a; sudo apt install build-essential3.验证GCC编译器是否已成功安装&#xff0c;请使用gcc --version命令打印GCC版本 rootubuntu:/home/csd# gcc --version

操作系统(五)输入/输出(I/O)管理

操作系统&#xff08;五&#xff09;输入/输出&#xff08;I/O&#xff09;管理一、I/O控制器二、I/O控制方式程序直接控制方式中断驱动方式DMA方式通道控制方式I/O软件层次结构假脱机技术设备的分配与回收缓冲区单缓冲双缓冲循环缓冲区缓冲池一、I/O控制器 I/O设备由机械部件…

Linux下的I/O多路复用select,poll,epoll浅析

转载&#xff1a;http://blog.csdn.net/u011573853/article/details/52105365 一&#xff0c;什么是I/O多路复用 所谓的I/O多路复用在英文中其实叫 I/O multiplexing. 就是单个线程&#xff0c;通过记录跟踪每个I/O流(sock)的状态&#xff0c;来同时管理多个I/O流 。) I/O mu…