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

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

在网络程序里面,通常都是一个服务器处理多个客户机,为了出个多个客户机的请求,服务器端的程序有不同的处理方式。本节开始介绍Linux下套接字编程的服务器模型选择,主要包括循环服务器模型、并发服务器模型、IO复用服务器模型等,这也是我们常见的几种网络服务器模型。其中基本可以分为两大类,

1. 循环服务器:循环服务器在同一时刻只能响应一个客户端的请求,是比较简单的一种模型;

2. 并发服务器:并发服务器在同一时刻可以响应多个客户端的请求,这里面又有很多分类,接下来会逐步介绍;

循环服务器模型

     循环服务器是指对于客户端的请求和连接,服务器逐个进行处理,处理完一个连接后再处理下一个连接,属于串行处理方式,结构比较简单。该模型的算法过程如下:

复制代码
/* UDP循环服务器模型 */ socket(); bind(); while(true)
{
   recvfrom(); process(); sendto(); 
} close();
复制代码
复制代码
/* TCP循环服务器模型 */ socket(); bind(); listen(); while(true) 
{ accept(); while(true) { recv(); process(); send(); } close(); 
}
复制代码

从上面的的流程可以看出,TCP循环服务器比UDP循环服务器多了一个accept的过程,这也是TCP和UDP套接字编程的主要区别。TCP服务器在accept出等待客户端的到来,因为accept函数是阻塞的,因此TCP服务器会在此等待(对accept函数的不同处理是区分各类服务器的一个重要参考依据)。相应地,UDP会在recvfrom阻塞,并等待客户端的连接。

一个循环服务器的例子

下面给出一个简单的循环服务器样子,模拟服务器对外提供时间服务器,等待客户端到来,并返回给客户端服务器的当前时间。

UDP循环服务器

复制代码
 1 /** UDP循环服务器--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 12345
10 int main(int argc, char *argv[])
11 {
12     int s;    //服务器套接字文件描述符
13     struct sockaddr_in local, to;    //本地地址
14     time_t now;        //时间
15     char buff[BUFFLEN];//收发数据缓冲区
16     int n = 0;
17     int len = sizeof(to);
18     
19     //建立UDP套接字
20     s = socket(AF_INET, SOCK_DGRAM, 0);
21     
22     //初始化地址
23     memset(&local, 0, sizeof(local));
24     local.sin_family = AF_INET;//AF_INET协议族
25     local.sin_addr.s_addr = htonl(INADDR_ANY);//任意本地地址
26     local.sin_port = htons(SERVER_PORT);//服务器端口
27     
28     //将套接字文件描述符绑定到本地地址和端口
29     int err = bind(s, (struct sockaddr*)&local, sizeof(local));
30     
31     //主处理过程
32     while(1)
33     {
34         memset(buff, 0, BUFFLEN);
35         n = recvfrom(s, buff, BUFFLEN,0,(struct sockaddr*)&to, &len);//接收发送方数据
36         if(n > 0 && !strncmp(buff, "TIME", 4))//判断是否合法接收数据
37         {
38             printf("Get One Client Connect\n");
39             memset(buff, 0, BUFFLEN);
40             now = time(NULL);
41             sprintf(buff, "%24s\r\n",ctime(&now));
42             sendto(s, buff, strlen(buff),0, (struct sockaddr*)&to, len);//发送数据
43         }
44     }
45     close(s);
46     
47     return 0;        
48 }
复制代码
复制代码
 1 /** UDP循环服务器--client端程序**/
 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 12345
10 int main(int argc, char *argv[])
11 {
12     int s;    //服务器套接字文件描述符
13     struct sockaddr_in server;    //本地地址
14     time_t now;         
15     char buff[BUFFLEN]; 
16     int n = 0;     
17     int len = 0;    //地址长度
18     
19     //建立UDP套接字
20     s = socket(AF_INET, SOCK_DGRAM, 0);
21     
22     //初始化地址接 
23     memset(&server, 0, sizeof(server));
24     server.sin_family = AF_INET;//AF_INET协议族
25     server.sin_addr.s_addr = htonl(INADDR_ANY);//任意本地地址
26     server.sin_port = htons(SERVER_PORT);//服务器端口
27     
28     memset(buff, 0, BUFFLEN); 
29     strcpy(buff, "TIME"); 
30     //发送数据
31     sendto(s, buff, strlen(buff), 0, (struct sockaddr*)&server, sizeof(server));
32     memset(buff, 0, BUFFLEN);
33     //接收数据
34     len = sizeof(server);
35     n = recvfrom(s, buff, BUFFLEN, 0, (struct sockaddr*)&server, &len);
36     if(n >0)
37         printf("TIME:%s",buff);    
38     
39     close(s);
40     
41     return 0;        
42 }
复制代码

  

TCP循环服务器

复制代码
 1 /** TCP循环服务器--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 12346
10 #define BACKLOG 5
11 int main(int argc, char *argv[])
12 {
13     int s_s, s_c;    /*服务器套接字文件描述符*/
14     struct sockaddr_in local, from;    /*本地地址*/
15     time_t now;        
16     char buff[BUFFLEN];
17     int n = 0;
18     int len = sizeof(from);
19     
20     /*建立TCP套接字*/
21     s_s = socket(AF_INET, SOCK_STREAM, 0);
22     
23     /*初始化地址*/
24     memset(&local, 0, sizeof(local));
25     local.sin_family = AF_INET;/*AF_INET协议族*/
26     local.sin_addr.s_addr = htonl(INADDR_ANY);/*任意本地地址*/
27     local.sin_port = htons(SERVER_PORT);/*服务器端口*/
28     
29     /*将套接字文件描述符绑定到本地地址和端口*/
30     int err = bind(s_s, (struct sockaddr*)&local, sizeof(local));
31     err = listen(s_s, BACKLOG);/*侦听*/
32     
33     /*主处理过程*/
34     while(1)
35     {
36         /*接收客户端连接*/
37         s_c = accept(s_s, (struct sockaddr*)&from, &len);
38         memset(buff, 0, BUFFLEN);
39         n = recv(s_c, buff, BUFFLEN,0);/*接收发送方数据*/
40         if(n > 0 && !strncmp(buff, "TIME", 4))/*判断是否合法接收数据*/
41         {
42             memset(buff, 0, BUFFLEN);
43             now = time(NULL);
44             sprintf(buff, "%24s\r\n",ctime(&now));
45             send(s_c, buff, strlen(buff),0);/*发送数据*/
46         }
47         close(s_c);
48     }
49     close(s_s);
50     
51     return 0;        
52 }
复制代码
 
复制代码
/**TCP循环服务器--client端程序**/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>#define BUFFLEN 1024
#define SERVER_PORT 12346
int main(int argc, char *argv[])
{int s;    /*服务器套接字文件描述符*/struct sockaddr_in server;    /*本地地址*/char buff[BUFFLEN];int n = 0;    /*建立TCP套接字*/s = socket(AF_INET, SOCK_STREAM, 0);/*初始化地址*/memset(&server, 0, sizeof(server));server.sin_family = AF_INET;/*AF_INET协议族*/server.sin_addr.s_addr = htonl(INADDR_ANY);/*任意本地地址*/server.sin_port = htons(SERVER_PORT);/*服务器端口*/    /*连接服务器*/int err = connect(s, (struct sockaddr*)&server,sizeof(server));memset(buff, 0, BUFFLEN);strcpy(buff, "TIME");/*发送数据*/send(s, buff, strlen(buff), 0);memset(buff, 0, BUFFLEN);/*接收数据*/    n = recv(s, buff, BUFFLEN, 0);if(n >0){printf("TIME:%s",buff);    }close(s);return 0;        
}
复制代码

 

两者返回给客户端的的输出都是一样的,比如:TIME:Sat Mar 22 15:26:25 2014

 

循环服务器的介绍就到这里。接下来介绍并发服务器模型。



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

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

相关文章

剑指Offer04. 二维数组中的查找

在一个 n * m 的二维数组中&#xff0c;每一行都按照从左到右递增的顺序排序&#xff0c;每一列都按照从上到下递增的顺序排序。请完成一个高效的函数&#xff0c;输入这样的一个二维数组和一个整数&#xff0c;判断数组中是否含有该整数。 相当于二叉搜索树,左孩子比根节点小&…

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

转载&#xff1a;http://www.cnblogs.com/lizhenghn/p/3617666.html 与循环服务器的串行处理不同&#xff0c;并发服务器对服务请求并发处理。循环服务器只能够一个一个的处理客户端的请求&#xff0c;显然效率很低。并发服务器通过建立多个子进程来实现对请求的并发处理。并发…

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

转载&#xff1a;http://www.cnblogs.com/lizhenghn/p/3618986.html 前面两篇文章&#xff08;参见&#xff09;分别介绍了循环服务器和简单的并发服务器网络模型&#xff0c;我们已经知道循环服务器模型效率较低&#xff0c;同一时刻只能为一个客户端提供服务&#xff0c;而且…

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

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

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.介质…

计算机网络(四)网络层

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

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

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

操作系统(二)进程管理

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.文件系…

如何在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…

计算机组成原理(一)计算机系统概述

计算机组成原理&#xff08;一&#xff09;计算机系统概述一、计算机系统层次结构冯诺伊曼机计算机工作过程多级层次结构一、计算机系统层次结构 冯诺伊曼机 特点&#xff1a; 计算机由五大部件组成指令和数据以同等地位存于存储 器&#xff0c;可按地址寻访指令和数据用二进…

计算机组成原理(二)数据的表示和运算

计算机组成原理&#xff08;二&#xff09;数据的表示和运算一、BCD码二、奇偶校验码三、海明码四、循环冗余校验码&#xff08;CRC&#xff09;五、乘法运算原码乘法补码乘法六、除法运算原码除法补码除法七、浮点数的表示与运算浮点数的运算一、BCD码 组合式BCD码&#xff1…

Linux IO复用区别与epoll详解

转载&#xff1a;http://blog.csdn.net/hacker00011000/article/details/52160590 一、select、poll、epoll之间的区别总结[整理]   select&#xff0c;poll&#xff0c;epoll都是IO多路复用的机制。I/O多路复用就通过一种机制&#xff0c;可以监视多个描述符&#xff0c;一…