IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> TCP服务器的编程模型有哪几种? -> 正文阅读

[系统运维]TCP服务器的编程模型有哪几种?

1.同步阻塞迭代模型

//创建socket
int sockfd = socket(...);
//准备通信地址
//绑定
bind(...);
//监听
listen(...);
for(;;)
{
	//等待连接
	accept(...);
	//接收客户端的请求
	recv(...);
	//响应请求
	send(...);
}

缺点:同步阻塞模型使用单进程,在accept、recv、send时都可能会发生阻塞,一次只能服务一个客户端,效率低。

  1. 若没有客户端发来连接请求,进程会阻塞在accept处,不能进行其它操作。
  2. recv函数用于接收客户端传送过来的信息,若客户端一直不发送消息,则进程会阻塞在这里。
  3. send函数用于向客户端发送信息,也可能发生阻塞。例如:客户端接受数据异常缓慢,导致写缓冲区满,数据迟迟发送不出。

优点:实现简单、占用资源少

2.多进程并发模型

多进程并发模型在同步阻塞迭代模型的基础上进行了改进,解决了一次只能服务一个客户端的问题。在接收到客户端的连接请求时,用fork函数为每一个客户端提供一个进程来处理客户端请求。

//创建socket
int sockfd = socket(...);
//准备要绑定的结构体addr
//绑定
bind(...);
//监听
listen(...);
for(;;)
{
	//等待连接
	accept(...);
	//创建子进程服务
	if(0 == fork())
	{
		//接收客户端的请求
		recv(...);
		//响应请求
		send(...);
		//关闭socket
		close(cli_fd);
	}
}

多进程并发模型通过创建子进程处理多并发的问题,看似有多个子进程同时工作,实际上只有一个CPU在处理,CPU轮流为每个进程服务一定时间,切换进程的过程中也会耗费一些时间。

3.多路复用模型

I/O多路复用就是通过一种机制,一个进程可以监视多个描述符,一旦
某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相
应的读写操作。

优点:不需要频繁地创建、销毁进程/线程,从而达到节约内存资源、时间资源,也能避免进程之间的竞争、等待。
缺点:单个客户端的任务不能耗时太长,否则其他客户端就会感知到。
适合并发量高、任务量短小的情景,例如:Web服务器
目前支持I/O多路复用的系统调用有 select,pselect,poll,epoll

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <arpa/inet.h>

typedef struct sockaddr* SP;

//TCP server
int main(int argc,const char* argv[])
{
	//创建socket对象
	int svr_fd = socket(AF_INET,SOCK_STREAM,0);
	if(0 > svr_fd)
	{
		perror("socket");
		return EXIT_FAILURE;
	}

	//准备通信地址
	struct sockaddr_in addr = {};
	addr.sin_family = AF_INET;
	addr.sin_port = htons(7788);
	addr.sin_addr.s_addr = INADDR_ANY;
	socklen_t addrlen = sizeof(addr);

	//绑定
	if(bind(svr_fd,(SP)&addr,addrlen))
	{
		perror("bind");
		return EXIT_FAILURE;
	}

	//监听
	if(listen(svr_fd,10))
	{
		perror("listen");
		return EXIT_FAILURE;
	}

	//定义一个文件描述符的集合并清空
	fd_set reads;
	FD_ZERO(&reads);

	//把已经监听好的socket描述符添加到集合中
	FD_SET(svr_fd,&reads);

	//定义超时时间
	struct timeval timeout = {5,500};

	//记录集合中最大的socket描述符
	int max_fd = svr_fd;
	
	char buf[4096] = {};
	for(;;)
	{
		//备份集合
		fd_set reads_copy = reads;

		//调用select 读操作
		int ret = select(max_fd+1,&reads_copy,NULL,NULL,&timeout);
		if(0 < ret)
		{
			//先测试等待连接的socket描述符(有客户端连接)
			if(FD_ISSET(svr_fd,&reads_copy))
			{
				//调用accept函数连接客户端
				int cli_fd = accept(svr_fd,(SP)&addr,&addrlen);
				if(0 > cli_fd)
				{
					perror("accept");
				}
				else
				{
					//把客户端的socket添加到监控的集合中
					FD_SET(cli_fd,&reads);
					if(cli_fd > max_fd)
					{
						max_fd = cli_fd;
					}
				}
			}
		
			//再测试其他的socket描述符是否发生读操作(有客户端发消息)
			for(int fd=3; fd <= max_fd; fd++)
			{
				if(FD_ISSET(fd,&reads_copy) && fd != svr_fd)
				{
					int ret = recv(fd,buf,sizeof(buf),0);
					if(0 > ret)
					{
						printf("客户端%d退出\n",fd);
						FD_CLR(fd,&reads);
						continue;
					}
					printf("recv:%s bits:%d\n",buf,ret);
					strcpy(buf,"return");
					ret = send(fd,buf,strlen(fd,buf,strlen(buf)+1,0));
					if(0 > ret)
					{
						printf("客户端%d退出\n",fd);
						FD_CLR(fd,&reads);
						continue;
					}
				}
			}
		}
	}
}
  1. select
优点缺点
它是最早的多路复用的函数,几乎所有的操作系统都支持,程序的兼容性高单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024。
每次调用select时都需要重新向它传递被监控者合集
调用结束后若想要知道哪些文件描述符发生了相关操作,需要把所有的被监控的文件描述符都测试一遍
  1. pselect
    与select大致相同
区别
超时时间的类型不同,pselect精度更高
pselect的timeout既是输入也是输出,可以返回剩余的时间,但是select只是输入
pselect监听时可以通过sigmask参数设置想要监听时屏蔽的信号,可以保证pselect的监听不被信号干扰
  1. poll
与select区别
它没有最大连接数的限制,原因是它是基于链表来存储的
调用结束后若想要知道哪些文件描述符发生了相关操作,只需要把所有的被监控的文件描述符都测试一遍
  1. epoll
  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-10-28 12:41:54  更:2021-10-28 12:44:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 22:44:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码