00. 目录

文章目录

  • 00. 目录
  • 01. 概述
  • 02. I/O复用技术概述
  • 03. select模型服务器实现思路
  • 04. select模型服务器实现
  • 05. 附录

01. 概述

服务器设计技术有很多,按使用的协议来分有 TCP 服务器UDP 服务器,按处理方式来分有循环服务器并发服务器

循环服务器与并发服务器模型

在网络程序里面,一般来说都是许多客户对应一个服务器(多对一),为了处理客户的请求,对服务端的程序就提出了特殊的要求。

目前最常用的服务器模型

  • 循环服务器:服务器在同一时刻只能响应一个客户端的请求。
  • 并发服务器:服务器在同一时刻可以响应多个客户端的请求。

02. I/O复用技术概述

I/O 复用技术是为了解决进程或线程阻塞到某个 I/O 系统调用而出现的技术,使进程不阻塞于某个特定的 I/O 系统调用。它也可用于并发服务器的设计,常用函数 select() 或 epoll() 来实现。

03. select模型服务器实现思路

socket(...); // 创建套接字
bind(...);   // 绑定
listen(...); // 监听while(1)
{if(select(...) > 0) // 检测监听套接字是否可读{if(FD_ISSET(...)>0) // 套接字可读,证明有新客户端连接服务器  {accpet(...);// 取出已经完成的连接process(...);// 处理请求,反馈结果}}close(...); // 关闭连接套接字:accept()返回的套接字
}

04. select模型服务器实现

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>#define SERV_PORT 8080
#define LIST 20                //服务器最大接受连接
#define MAX_FD 10              //FD_SET支持描述符数量int main(int argc, char *argv[])
{int sockfd;int err;int i;int connfd;int fd_all[MAX_FD]; //保存所有描述符,用于select调用后,判断哪个可读//下面两个备份原因是select调用后,会发生变化,再次调用select前,需要重新赋值fd_set fd_read;    //FD_SET数据备份fd_set fd_select;  //用于selectstruct timeval timeout;         //超时时间备份struct timeval timeout_select;  //用于selectstruct sockaddr_in serv_addr;   //服务器地址struct sockaddr_in cli_addr;    //客户端地址socklen_t serv_len;socklen_t cli_len;//超时时间设置timeout.tv_sec = 10;timeout.tv_usec = 0;//创建TCP套接字sockfd = socket(AF_INET, SOCK_STREAM, 0);if(sockfd < 0){perror("fail to socket");exit(1);}// 配置本地地址memset(&serv_addr, 0, sizeof(serv_addr));serv_addr.sin_family = AF_INET;            // ipv4serv_addr.sin_port = htons(SERV_PORT);  // 端口, 8080serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); // ipserv_len = sizeof(serv_addr);// 绑定err = bind(sockfd, (struct sockaddr *)&serv_addr, serv_len);if(err < 0){perror("fail to bind");exit(1);}// 监听err = listen(sockfd, LIST);if(err < 0){perror("fail to listen");exit(1);}//初始化fd_all数组memset(&fd_all, -1, sizeof(fd_all));fd_all[0] = sockfd;   //第一个为监听套接字FD_ZERO(&fd_read);   // 清空FD_SET(sockfd, &fd_read);  //将监听套接字加入fd_readint maxfd;maxfd = fd_all[0];  //监听的最大套接字while(1){// 每次都需要重新赋值,fd_select,timeout_select每次都会变fd_select = fd_read;timeout_select = timeout;// 检测监听套接字是否可读,没有可读,此函数会阻塞// 只要有客户连接,或断开连接,select()都会往下执行err = select(maxfd+1, &fd_select, NULL, NULL, NULL);//err = select(maxfd+1, &fd_select, NULL, NULL, (struct timeval *)&timeout_select);if(err < 0){perror("fail to select");exit(1);}if(err == 0){printf("timeout\n");}// 检测监听套接字是否可读if( FD_ISSET(sockfd, &fd_select) ){//可读,证明有新客户端连接服务器cli_len = sizeof(cli_addr);// 取出已经完成的连接connfd = accept(sockfd, (struct sockaddr *)&cli_addr, &cli_len);if(connfd < 0){perror("fail to accept");exit(1);}// 打印客户端的 ip 和端口char cli_ip[INET_ADDRSTRLEN] = {0};inet_ntop(AF_INET, &cli_addr.sin_addr, cli_ip, INET_ADDRSTRLEN);printf("----------------------------------------------\n");printf("client ip=%s,port=%d\n", cli_ip,ntohs(cli_addr.sin_port));// 将新连接套接字加入 fd_all 及 fd_readfor(i=0; i < MAX_FD; i++){if(fd_all[i] != -1){continue;}else{fd_all[i] = connfd;printf("client fd_all[%d] join\n", i);break;}}FD_SET(connfd, &fd_read);if(maxfd < connfd){maxfd = connfd;  //更新maxfd}}//从1开始查看连接套接字是否可读,因为上面已经处理过0(sockfd)for(i=1; i < maxfd; i++){if(FD_ISSET(fd_all[i], &fd_select)){printf("fd_all[%d] is ok\n", i);char buf[1024]={0};  //读写缓冲区int num = read(fd_all[i], buf, 1024);if(num > 0){//收到 客户端数据并打印printf("receive buf from client fd_all[%d] is: %s\n", i, buf);//回复客户端num = write(fd_all[i], buf, num);if(num < 0){perror("fail to write ");exit(1);}else{//printf("send reply\n");}}else if(0 == num){ // 客户端断开时//客户端退出,关闭套接字,并从监听集合清除printf("client:fd_all[%d] exit\n", i);FD_CLR(fd_all[i], &fd_read);close(fd_all[i]);fd_all[i] = -1;continue;}}else {//printf("no data\n");                  }}}return 0;
}

05. 附录

5.1【Linux】一步一步学Linux网络编程教程汇总

【Linux网络编程】并发服务器之select模型相关推荐

  1. linux网络编程(三)select、poll和epoll

    linux网络编程(三)select.poll和epoll 一.为什么会有多路I/O转接服务器? 二.select 三.poll 三.epoll 一.为什么会有多路I/O转接服务器? 为什么会有多路I ...

  2. Linux io模型及函数调用,Linux 网络编程的5种IO模型:信号驱动IO模型

    Linux 网络编程的5种IO模型:信号驱动IO模型 背景 这一讲我们来看 信号驱动IO 模型. 介绍 情景引入: 在信号驱动IO模型中,当用户线程发起一个IO请求操作,会给对应的socket注册一个 ...

  3. 【Linux网络编程】并发服务器之多线程模型

    00. 目录 文章目录 00. 目录 01. 概述 02. 多线程服务器 03. 多线程服务器实现思路 04. 多线程服务器实现 05. 附录 01. 概述 服务器设计技术有很多,按使用的协议来分有 ...

  4. 【Linux网络编程】并发服务器之多进程模型

    00. 目录 文章目录 00. 目录 01. 概述 02. 多进程并发服务器 03. 多进程并发服务器实现思路 04. 多进程并发服务器实现 05. 附录 01. 概述 服务器设计技术有很多,按使用的 ...

  5. Linux 网络编程——并发服务器的三种实现模型

    服务器设计技术有很多,按使用的协议来分有 TCP 服务器和 UDP 服务器,按处理方式来分有循环服务器和并发服务器. 循环服务器与并发服务器模型 在网络程序里面,一般来说都是许多客户对应一个服务器(多 ...

  6. Linux网络编程 | 并发模式:半同步/半异步模式、领导者/追随者模式

    文章目录 同步与异步 半同步/半异步模式 变体:半同步/半反应堆模式 改进:更高效的半同步/半异步模式 领导者/追随者模式 组件 :句柄集.线程集.事件处理器 并发模式是指I/O处理单元和多个逻辑单元 ...

  7. Linux网络编程 之 IO多路复用select(八)

    1. IO多路复用的概念 I/O多路复用是通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作. 2. select接口 #include & ...

  8. 【Linux】一步一步学Linux网络编程教程汇总(更新中......)

    00. 目录 文章目录 00. 目录 01. 基础理论知识 02. 初级编程 03. 高级编程 04. LibEvent库 05. 06. 07. 01. 基础理论知识 [Linux网络编程]网络协议 ...

  9. 【Linux网络编程】循环服务器之TCP模型

    00. 目录 文章目录 00. 目录 01. 概述 02. TCP循环服务器实现方法 03. TCP循环服务器模型 04. TCP循环服务器实现 05. 附录 01. 概述 服务器设计技术有很多,按使 ...

最新文章

  1. Failed to read artifact descriptor for xxx:jar:版本号
  2. 3des java ecb_PHP 3DES加密 与JAVA通用 加密模式:ECB
  3. ReactNative ES6简介 及基本语法第一篇
  4. 字符串科技:Palindrome Series
  5. ef执行原生sql语句_EF Core中执行原生SQL语句
  6. Centos7 修改、更换源
  7. 京东发布虎年春晚互动攻略 春晚联名款金碗套装首次曝光
  8. Linux***检测基础学习
  9. 有哪些类目适合刚创业的新手淘宝卖家做?
  10. 能源消耗总量计算公式_电力消耗占比计算公式
  11. 答题小程序 服务器,开源的基于云开发的在线答题小程序
  12. 判断质数的所有方法详解(C语言)
  13. Python代码规范之---代码不规范,亲人两行泪
  14. 用mysql设计一个KTV点歌系统_KTV点歌系统(JAVA+MYSQL)
  15. 机器学习mAP之我见
  16. 1、zstack协议栈
  17. 转:一套大而全的系统架构体系与具体落地方案
  18. Kafka Eagle Consumers不显示
  19. 归并排序的思想以及应用——试解《逆序对的数量》
  20. BootStrap-Table主子表

热门文章

  1. 自己编写jQuery插件之表单验证
  2. 禁用FCKeditor浏览服务器
  3. SilverLight学习笔记--WCF服务
  4. sql导入excel数据失败_nifi入门从Excel数据导入ES开始
  5. 阿里云2011.9.17招聘会笔试题
  6. atoi() 与 itoa()函数的内部实现
  7. Exit- Linux必学的60个命令
  8. php大并发 大流量 大存储解决方案
  9. bzoj1878: [SDOI2009]HH的项链
  10. Linux自定义命令