当前位置: 首页 > news >正文

南昌企业网站设计建设制作图书馆网站建设建议

南昌企业网站设计建设制作,图书馆网站建设建议,wordpress 图片样式,建信网证书查询平台目录 一.常见的IO模型介绍二.多路转接I/O1.select1.1.函数解析1.2. select特点和缺点1.3.基于 select 的多客户端网络服务器 2.poll2.1.poll函数解析2.2.poll特点和缺点2.3.基于poll的tcp服务器 3.epoll3.1.系列函数解析3.2.epoll原理解析2.3.基于 select 的多客户端网络服务器… 目录 一.常见的IO模型介绍二.多路转接I/O1.select1.1.函数解析1.2. select特点和缺点1.3.基于 select 的多客户端网络服务器 2.poll2.1.poll函数解析2.2.poll特点和缺点2.3.基于poll的tcp服务器 3.epoll3.1.系列函数解析3.2.epoll原理解析2.3.基于 select 的多客户端网络服务器3.4.epoll的优点 三.LT和ET 一.常见的IO模型介绍 在 Linux 中主要有以下几种 I/O 模型 阻塞 I/O在阻塞 I/O 模型中当进程请求 I/O 操作时它会被挂起直到该操作完成。这种方式进程在等待 I/O 的同时不能做其他的事。非阻塞 I/O非阻塞 I/O 允许进程发出 I/O 请求后立即返回进程可以继续执行其他操作。为了检查 I/O 是否完成进程需要通过轮询方式不断检查状态所以也常称为非阻塞轮询IO这种方式可以减少等待时间但是在高频率轮询时很消耗cpu资源。I/O 多路复用I/O 多路复用通过使用 select、poll 或 epoll 等系统调用使一个进程/线程能够同时监视多个文件描述符。该模型在处理多个并发连接时效率较高适合网络服务器等应用场景。信号驱动 I/O在信号驱动 I/O 模型中进程在发出 I/O 请求后可以继续执行其他任务操作的完成通过信号通知。这种方式可以减少轮询但是处理起来较为复杂。异步 I/O异步 I/O 是最先进的模型进程发出 I/O 请求后立即返回并在操作完成时通过回调函数或其他机制获得通知。异步 I/O 模型通常提供最高的性能适合高负载、高并发的应用程序。 二.多路转接I/O 1.select 1.1.函数解析 #include sys/select.hint pselect(int nfds, fd_set *restrict readfds,fd_set *restrict writefds, fd_set *restrict errorfds,const struct timespec *restrict timeout,const sigset_t *restrict sigmask);int select(int nfds, fd_set *restrict readfds,fd_set *restrict writefds, fd_set *restrict errorfds,struct timeval *restrict timeout);void FD_CLR(int fd, fd_set *fdset); int FD_ISSET(int fd, fd_set *fdset); void FD_SET(int fd, fd_set *fdset); void FD_ZERO(fd_set *fdset);nfds待监视的文件描述符最大值 1。readfds指向一组需要监视“可读”事件的文件描述符集合。writefds指向一组需要监视“可写”事件的文件描述符集合。exceptfds指向一组需要监视异常事件的文件描述符集合。timeouttimeout 是一个 struct timeval 结构体包含等待的秒数和微秒数如果在超时时间内有文件描述符变为可用状态select 会返回返回值是可用的文件描述符数量。如果发生错误select 返回 -1并设置 errno。select 函数返回就绪的文件描述符数如果返回 0 则表示超时。 fd_set的介绍 fd_set 是一个位图结构用于存储多个文件描述符。select 使用宏来操作 fd_set常见的宏有 FD_ZERO(fd_set *set)将文件描述符集合置空。 FD_SET(int fd, fd_set *set)将文件描述符 fd加入集合。 FD_CLR(int fd, fd_set *set)将文件描述符 fd 从集合中移除。 FD_ISSET(int fd, fd_set *set)检查文件描述符 fd 是否在集合中并且是否准备就绪。 下面是一个简单的使用演示代码 fd_set readfds; FD_ZERO(readfds); FD_SET(sockfd, readfds); int maxfd sockfd 1;int result select(maxfd, readfds, nullptr, nullptr, nullptr); if (result 0) {if (FD_ISSET(sockfd, readfds)) {// 处理读操作} }初始化fd_set集合将需要监控的fd添加进去接着调用select函数maxfd是需要监控的fd集合中最大值再加1select可以同时监控读事件、写事件、异常事件。timeout设置为nullptr标识阻塞等待直到事件有就绪的或者出错。 1.2. select特点和缺点 特点 多路复用select 允许一个进程同时监控多个文件描述符等待其中一个或多个变为可读、可写或异常状态。可以处理不同类型的文件描述符:能够监控常规文件、套接字、管道等多种类型的文件描述符。跨平台支持:在许多 Unix-like 操作系统以及 Windows 中都有支持具有良好的移植性。 缺点 性能瓶颈:当监控的文件描述符数量很大时select 的性能会显著下降。每次调用 select 都需要遍历所有文件描述符增加了开销。文件描述符数量限制:select 有文件描述符的数量限制通常是 1024取决于类型fd_set的大小超过这个限制就不能监控更多的描述符。每次调用都需要重置:每次调用 select 都需要重新设置文件描述符集合这在处理多个连接时会带来额外的开销。无优先级支持:select 不能为不同的文件描述符设置优先级所有的描述符在监控时是平等的。不适合高并发场景:在高并发情况下如数千个连接select 的效率会下降通常需要使用其他机制如 poll、epoll 或 kqueue来更好地处理大量并发连接。 1.3.基于 select 的多客户端网络服务器 下面我们来实现一个简单的基于 select 的 TCP 服务器来窥探他的使用附上详细注释 #pragma once#include iostream #include sys/select.h #include sys/time.h #include string#include Socket.hppusing namespace std;// 默认端口号 static const uint16_t defaultport 8888; // 最大文件描述符数量 static const int fd_num_max (sizeof(fd_set) * 8); int defaultfd -1; // 默认文件描述符表示未使用class SelectServer { public:// 构造函数初始化端口和文件描述符数组SelectServer(uint16_t port defaultport) : _port(port){for (int i 0; i fd_num_max; i){fd_array[i] defaultfd; // 初始化所有文件描述符为默认值}}// 初始化服务器创建套接字、绑定和监听bool Init(){_listensock.Socket(); // 创建套接字_listensock.Bind(_port); // 绑定到指定端口_listensock.Listen(); // 开始监听return true;}// 接受新的连接void Accepter(){// 处理连接事件string clientip; // 客户端IPuint16_t clientport 0; // 客户端端口int sock _listensock.Accept(clientip, clientport); // 接受连接if (sock 0) return; // 失败则返回// 将新连接的sock添加到fd_array数组int pos 1; // 从1开始0位置为监听套接字for (; pos fd_num_max; pos) // 查找可用的位置{if (fd_array[pos] ! defaultfd)continue; // 当前位置已被占用继续查找elsebreak; // 找到可用位置}if (pos fd_num_max) // 如果数组已满{close(sock); // 关闭新连接}else // 有空位{fd_array[pos] sock; // 存储新连接的文件描述符}}// 接收数据void Recver(int fd, int pos){char buffer[1024]; // 缓冲区ssize_t n read(fd, buffer, sizeof(buffer) - 1); // 读取数据if (n 0) // 有数据到达{buffer[n] 0; // 结束符cout get a messge: buffer endl; // 输出接收到的信息}else if (n 0) // 客户端关闭连接{close(fd); // 关闭连接fd_array[pos] defaultfd; // 从数组中移除}else // 发生错误{close(fd); // 关闭连接fd_array[pos] defaultfd; // 从数组中移除}}// 分发事件void Dispatcher(fd_set rfds){for (int i 0; i fd_num_max; i) // 遍历文件描述符数组{int fd fd_array[i];if (fd defaultfd)continue; // 跳过未使用的描述符if (FD_ISSET(fd, rfds)) // 检查描述符是否就绪{if (fd _listensock.Fd()) // 如果是监听套接字{Accepter(); // 处理新连接}else // 其他连接{Recver(fd, i); // 接收数据}}}}// 启动服务器void Start(){int listensock _listensock.Fd(); // 获取监听套接字的文件描述符fd_array[0] listensock; // 将监听套接字放入数组的第一个位置while (true){fd_set rfds; // 文件描述符集合FD_ZERO(rfds); // 清空集合int maxfd fd_array[0]; // 最大文件描述符for (int i 0; i fd_num_max; i) // 遍历文件描述符数组{if (fd_array[i] defaultfd)continue; // 跳过未使用的描述符FD_SET(fd_array[i], rfds); // 将就绪的描述符加入集合if (maxfd fd_array[i]) // 更新最大文件描述符{maxfd fd_array[i];}}// 设置超时为 0非阻塞轮询struct timeval timeout {0, 0}; // 超时设置为 0// 调用 select 检测事件int n select(maxfd 1, rfds, nullptr, nullptr, timeout);switch (n){case 0:cout time out, timeout: timeout.tv_sec . timeout.tv_usec endl; // 超时处理break;case -1:cerr select error endl; // 错误处理break;default:cout get a new link!!!!! endl;Dispatcher(rfds); // 处理就绪的事件break;}}}// 析构函数关闭监听套接字~SelectServer(){_listensock.Close(); // 关闭套接字}private:Sock _listensock; // 监听套接字对象uint16_t _port; // 服务器端口int fd_array[fd_num_max]; // 文件描述符数组用于维护连接 }; 2.poll 2.1.poll函数解析 #include poll.hint poll(struct pollfd *fds, nfds_t nfds, int timeout);fds: 传入一个结构体数组用于保存需要监控的文件描述符以及感兴趣的事件。nfds: 数组 fds 中的文件描述符个数。timeout: 指定超时时间单位为毫秒。返回值小于0表示出错等于表示超时大于0表示事件就绪。 pollfd 结构体 struct pollfd {int fd; // 文件描述符short events; // 需要监控的事件short revents; // 实际发生的事件由 poll 填充 };fd: 需要监控的文件描述符。events: 指定感兴趣的事件比如 POLLIN可读、POLLOUT可写等。revents: 存储实际发生的事件由 poll 调用后填充。 events和revents的取值: 事件类型events 值revents 值描述可读事件POLLINPOLLIN数据可读通常指套接字上有数据可读可写事件POLLOUTPOLLOUT数据可写通常指套接字可以发送数据错误事件POLLERRPOLLERR发生错误需要处理挂起事件POLLHUPPOLLHUP连接已关闭或挂起非法请求POLLNVALPOLLNVAL监控的文件描述符无效超时--当设置的超时时间到达但没有事件发生 2.2.poll特点和缺点 poll的优点 无文件描述符限制与 select 不同poll 不受文件描述符数量的限制因此可以处理更多的连接。简单性poll 的使用相对select简单容易理解和实现。 poll的缺点 线性扫描在事件发生时poll 会线性扫描所有文件描述符效率较低。对于大量文件描述符响应时间可能变长。性能问题每次调用 poll 时都需要传递整个文件描述符数组性能降低不支持边缘触发poll **不支持边缘触发模式 2.3.基于poll的tcp服务器 下面我们来实现一个简单的基于poll的 TCP 服务器来窥探他的使用附上详细注释 #pragma once#include iostream #include poll.h // 引入poll头文件用于多路复用 #include sys/time.h // 时间操作相关 #include Socket.hpp // 自定义的Socket类封装了socket的基本操作using namespace std;static const uint16_t defaultport 8888; // 默认监听端口号为8888 static const int fd_num_max 128; // 最大支持的文件描述符数量 int defaultfd -1; // 默认无效的文件描述符值 const int _no events 0; // 无事件标志class PollServer { public:// 构造函数初始化监听端口号并设置poll事件数组PollServer(uint16_t port defaultport) : _port(port){for (int i 0; i fd_num_max; i) // 初始化所有的文件描述符和事件{_event_fds[i].fd defaultfd; // 将所有文件描述符设置为默认值_event_fds[i].events _no events; // 清空所有事件类型_event_fds[i].revents _no events; // 清空所有返回事件}}// 初始化服务器创建监听套接字并绑定到指定端口bool Init(){_listensock.Socket(); // 创建监听socket_listensock.Bind(_port); // 绑定到指定端口_listensock.Listen(); // 开始监听return true; // 初始化成功返回true}// 处理新连接的客户端void Accepter(){// 有新的连接事件触发接收连接string clientip; // 用于存储客户端IP地址uint16_t clientport 0; // 用于存储客户端端口号int sock _listensock.Accept(clientip, clientport); // 接收客户端连接返回新socketif (sock 0) return; // 如果返回值小于0表示接收失败// 将新连接的socket放入_event_fds数组int pos 1;for (; pos fd_num_max; pos) // 查找空闲的数组位置{if (_event_fds[pos].fd ! defaultfd) // 如果当前文件描述符已经被占用继续寻找continue;elsebreak; // 找到空闲位置退出循环}if (pos fd_num_max) // 如果位置满了无法接收更多客户端{close(sock); // 关闭新连接}else{// 将新socket添加到poll事件数组中监听读事件_event_fds[pos].fd sock;_event_fds[pos].events POLLIN; // 监听读事件_event_fds[pos].revents _no events; // 初始化返回事件PrintFd(); // 打印当前在线的fd列表}}// 处理客户端发送过来的消息void Recver(int fd, int pos){char buffer[1024]; // 接收数据的缓冲区ssize_t n read(fd, buffer, sizeof(buffer) - 1); // 从客户端读取数据if (n 0) // 正常读取到数据{buffer[n] 0; // 将数据末尾补上字符串结束符cout get a messge: buffer endl; // 打印接收到的消息}else if (n 0) // 客户端主动断开连接{close(fd); // 关闭文件描述符_event_fds[pos].fd defaultfd; // 从事件数组中移除该客户端}else // 读取出错{close(fd); // 关闭文件描述符_event_fds[pos].fd defaultfd; // 从事件数组中移除该客户端}}// 事件分发器处理所有准备好的事件void Dispatcher(){for (int i 0; i fd_num_max; i) // 遍历所有的文件描述符{int fd _event_fds[i].fd;if (fd defaultfd) // 如果是默认值说明该位置空闲跳过continue;if (_event_fds[i].revents POLLIN) // 如果当前文件描述符有读事件{if (fd _listensock.Fd()) // 如果是监听socket上的事件处理新的连接{Accepter(); // 处理新连接}else // 如果是普通客户端socket上的事件{Recver(fd, i); // 接收客户端消息}}}}// 服务器主循环启动服务器并进入事件处理void Start(){_event_fds[0].fd _listensock.Fd(); // 将监听socket放入第一个位置_event_fds[0].events POLLIN; // 监听读事件int timeout 1000; // 设置poll的超时时间为3秒for (;;){// 调用poll函数监控事件int n poll(_event_fds, fd_num_max, timeout);switch (n){case 0: // 超时无事件cout time out... endl;break;case -1: // 发生错误cerr poll error endl;break;default: // 有事件发生cout get a new link!!!!! endl;Dispatcher(); // 分发处理就绪的事件break;}}}// 打印当前在线的文件描述符列表void PrintFd(){cout fd list: ;for (int i 0; i fd_num_max; i) // 遍历所有的文件描述符{if (_event_fds[i].fd defaultfd) // 跳过无效的文件描述符continue;cout _event_fds[i].fd ; // 打印文件描述符}cout endl;}// 析构函数关闭监听socket~PollServer(){_listensock.Close();}private:Sock _listensock; // 自定义封装的监听socketuint16_t _port; // 服务器监听的端口号struct pollfd _event_fds[fd_num_max]; // poll事件数组保存所有的文件描述符及其事件 }; 3.epoll epoll 是 Linux 下用于处理 I/O 事件的高效多路复用机制适用于需要处理大量并发连接的网络服务器相较于poll提供了更好的性能可以说是他的升级版。 3.1.系列函数解析 int epoll_create(int size);创建一个 epoll 实例返回一个文件描述符指向的struct_file对象细节在原理讲解用于后续的 epoll_ctl 和 epoll_wait 调用。 参数 size指定要监听的最大文件描述符数量。返回值成功返回 epoll 文件描述符失败返回 -1 并设置 errno。 int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);控制 epoll 实例的行为包括添加、修改或删除文件描述符的事件。 参数 epfd由 epoll_create 返回的 epoll 文件描述符。op操作类型可以是以下之一 EPOLL_CTL_ADD添加文件描述符。EPOLL_CTL_MOD修改文件描述符。EPOLL_CTL_DEL删除文件描述符。 fd要操作的文件描述符。event指向 epoll_event 结构的指针描述要监听的事件。返回值成功返回 0失败返回 -1 并设置 errno。 epoll_event 结构: struct epoll_event {uint32_t events; // 事件类型epoll_data_t data; // 用户数据 }; union epoll_data {void *ptr; // 用户自定义数据指针int fd; // 文件描述符uint32_t u32; // 无符号整型数据uint64_t u64; // 无符号长整型数据 };events 类型uint32_t描述要监听的事件类型可以多个组合。常用的事件类型包括 EPOLLIN表示文件描述符可读。 EPOLLOUT表示文件描述符可写。 EPOLLERR表示发生错误。 EPOLLHUP表示挂起事件。 EPOLLET边缘触发模式Edge Triggered意味着在状态变化时才通知。 使用示例 struct epoll_event event; event.events EPOLLIN | EPOLLET; // 监听可读事件设置为边缘触发模式 event.data.fd socket_fd; // 关联的文件描述符int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);功能等待事件发生返回已就绪的个数。 参数 epfd由 epoll_create 返回的 epoll 文件描述符。events保存就绪事件。maxeventsevents 数组的大小。timeout等待的时间单位是毫秒。可以设置为 0不阻塞-1永久等待或正值指定超时时间。返回值成功时返回就绪事件的数量失败返回 -1 并设置 errno。 3.2.epoll原理解析 当调用 epoll_create 时内核会执行以下操作 L创建一个 eventpoll 结构体实例用于管理注册的文件描述符及其事件。返回一个文件描述符fd该 fd 代表了 eventpoll 结构体。 eventpoll 结构体内容 struct eventpoll {struct list_head wq_entry; // 等待队列条目用于管理等待事件的线程struct hlist_head rdlist; // 用于管理注册的可读事件的文件描述符struct hlist_head pr_list; // 用于优先级处理的链表struct rb_root rbr_tree; // 红黑树管理注册的文件描述符struct rb_root rbr_wait; // 等待事件的红黑树wait_queue_head_t wait; // 等待队列用于线程调度int epfd; // epoll 文件描述符int wakeup; // 唤醒标志// 其他字段... };主要使用过程解析连接基于tcp实现的epoll多客户端网络服务器后将需要监控的fd添加到红黑树rbr_tree等待网卡数据就绪发送中断信号将数据向上交付后在红黑树查找到对应的fd将此结点包含fd和对应事件插入就绪队列中wq_entry便于用户调用epoll_wait获取就绪节点。 epoll模型原理 2.3.基于 select 的多客户端网络服务器 #pragma once#include iostream #include memory #include sys/epoll.h #include Socket.hpp #include Epoller.hpp using namespace std;// 定义事件常量 const int num 64; // epoll 事件数组的最大数量// EpollServer 类用于处理基于 epoll 的服务器逻辑 class EpollServer {public:// 构造函数初始化端口、监听套接字和 epollerEpollServer(uint16_t port): _port(port),_listsocket_ptr(new Sock()), // 创建一个新的套接字对象_epoller_ptr(new Epoller()) // 创建一个新的 epoller 对象{}// 初始化服务器void Init(){_listsocket_ptr-Socket(); // 创建套接字_listsocket_ptr-Bind(_port); // 绑定端口_listsocket_ptr-Listen(); // 开始监听 }// 接收新连接void Accepter(){string clientip; // 客户端 IP 地址uint16_t clientport; // 客户端端口int sock _listsocket_ptr-Accept(clientip, clientport); // 接收新连接if (sock 0){// 将新连接的套接字添加到 epoll 中进行事件监听_epoller_ptr-EpllerUpdate(EPOLL_CTL_ADD, sock, EPOLLIN);}}// 测试用的接收函数void Recver(int fd){char buffer[1024]; // 接收缓冲区ssize_t n read(fd, buffer, sizeof(buffer) - 1); // 读取数据if (n 0){buffer[n] 0; // 确保字符串结束cout get a messge: buffer endl; // 输出接收到的消息// 发送回显消息string echo_str server echo $ ;echo_str buffer;write(fd, echo_str.c_str(), echo_str.size());}else if (n 0){_epoller_ptr-EpllerUpdate(EPOLL_CTL_DEL, fd, 0); // 从 epoll 中移除close(fd); // 关闭套接字}else{// 发生接收错误_epoller_ptr-EpllerUpdate(EPOLL_CTL_DEL, fd, 0); // 从 epoll 中移除close(fd); // 关闭套接字}}// 分发事件处理void Dispatcher(struct epoll_event revs[], int num){for (int i 0; i num; i){uint32_t events revs[i].events; // 获取事件类型int fd revs[i].data.fd; // 获取文件描述符if (events EPOLLIN) // 可读事件{if (fd _listsocket_ptr-Fd()) // 如果是监听套接字{Accepter(); // 接受新连接}else{// 处理普通套接字的可读事件Recver(fd);}}else{}}}// 启动服务器void Start(){// 将监听套接字添加到 epoll 中进行事件监听_epoller_ptr-EpllerUpdate(EPOLL_CTL_ADD, _listsocket_ptr-Fd(), EPOLLIN);struct epoll_event temp[num]; // 创建事件数组while(true){int n _epoller_ptr-EpollerWait(revs, num); // 等待事件发生if (n 0){// 有事件就绪Dispatcher(temp, n); // 分发事件}else if (n 0){lg(Info, time out ...); // 超时日志}else{lg(Error, epll wait error); // 错误日志}}}// 析构函数关闭监听套接字~EpollServer(){_listsocket_ptr-Close(); // 关闭监听套接字}private:shared_ptrSock _listsocket_ptr; // 监听套接字指针shared_ptrEpoller _epoller_ptr; // epoller 指针uint16_t _port; // 服务器端口 };Epoll.hpp #pragma once#include cerrno #include cstring #include sys/epoll.hclass Epoller {static const int size 128;public:Epoller(){_epfd epoll_create(size);if (_epfd -1){}else{coutepoll_create success _epfdendl;}}int EpollerWait(struct epoll_event revents[], int num){int n epoll_wait(_epfd, revents, num, -1);return n;}int EpllerUpdate(int oper, int sock, uint32_t event){int n 0;if (oper EPOLL_CTL_DEL){n epoll_ctl(_epfd, oper, sock, nullptr);if (n ! 0){coutepoll_ctl errorendl;}}else{struct epoll_event ev;ev.events event;ev.data.fd sock;n epoll_ctl(_epfd, oper, sock, ev);if (n ! 0){coutepoll_ctl errorendl;}}return n;}~Epoller(){if (_epfd 0)close(_epfd);}private:int _epfd;int _timeout{1000}; };3.4.epoll的优点 高性能相比于 select 和 pollepoll 在处理大量文件描述符时性能更优尤其是在有很多文件描述符处于非活动状态时。epoll 使用内核中的红黑树和链表来管理文件描述符能够快速地插入、删除和查找事件。支持边缘触发和水平触发epoll 支持两种工作模式水平触发Level Triggered, LT默认模式只有当文件描述符处于可读或可写状态时epoll_wait 才会返回。边缘触发Edge Triggered, ET只有在状态改变时才会通知这意味着你需要在事件发生时一次性读取所有数据这种模式更加高效但需要开发者小心处理。不限制文件描述符数量epoll 可以处理的文件描述符数量大于 select 的 1024 限制具体数量仅受系统资源限制。减少上下文切换epoll 通过在内核中管理事件减少了用户空间和内核空间之间的切换从而提高了性能。 三.LT和ET epoll 的 LT 和 ET 模式解析 epoll 提供了两种工作模式水平触发Level Triggered, LT和边缘触发Edge Triggered, ET。这两种模式适用于不同的场景epoll默认是LT。 1. 水平触发LT 工作方式 在 LT 模式下只要文件描述符处于可读或可写状态epoll_wait 就会返回该文件描述符。如果文件描述符有未读的数据epoll_wait 会多次通知即使在没有新数据到达的情况下只要状态满足条件它都会返回支持阻塞读写和非阻塞读写。 2. 边缘触发ET 工作方式 在 ET 模式下epoll_wait 只在状态变化时通知事件。例如文件描述符从不可读变为可读时才会触发。一旦事件被触发开发者需要尽可能地读取所有可用数据直到 EAGAIN 错误出现只支持非阻塞的读写。每次通知都必须把本轮的数据全取走必须非阻塞读。 LT 适用场景 简单的应用场景或者对性能要求不高的情况。需要处理大量连接但不要求高并发性能的应用。 ET 适用场景 高性能网络服务处理大量并发连接的场景如高负载的 Web 服务器。需要尽量减少系统调用次数提升性能的应用。
http://www.dnsts.com.cn/news/127936.html

相关文章:

  • 搭建网站是什么意思建设网站都要什么
  • 做川菜的网站建设银行大学华东学院网站
  • 湖南长沙房价2023年最新房价邢台seo关键词引流
  • 网站如何开发触屏版小程序开发公司排行榜前10
  • dede做招聘网站西宁网站建设天锐科技
  • 潍坊cms建站系统十堰网站建设有哪些公司
  • 长治市城乡建设局网站戈韦思网站建设
  • 一般网站模块域名服务网站
  • 河南国控建设集团网站那个网站百度收录好
  • 浙江华企做的网站怎么样百度联盟网站怎么做
  • 云主机上传网站商城模板html
  • 大连网站建设谁家好贵阳网站设计公司
  • 专业的单位网站建设做外贸网站注册什么邮箱
  • 贵州建设监理协会网站进不了石家庄服务大型建站
  • 石狮外贸网站建设公司报价营销活动方案模板
  • 织梦系统做的网站打开慢织梦做的网站 xampp
  • 汝州市住房和城乡规划建设局网站徐州建设工程交易网站
  • 自己做的网站能放到网上么宁波网站建设设计制作
  • 合肥企业快速建站Wordpress页面有横线
  • 怎么开一个网站平台电商平面设计图
  • 福建省建设执业注册中心网站流程优化的方法
  • 四川内江网站建设西安专业网站开发联系电话
  • 网站没有收录了wordpress安装到服务器
  • 泰安做网站建设的公司吉林seo关键词
  • 微信订阅号 网站开发百度怎么建网站
  • 郑州好的网站建站手机app如何开发制作
  • 湖州网站建设湖州网站建设最低多少钱
  • 学做网站开发要1万6wordpress如何设置外网访问
  • 移动做网站吗网站建设公司类型
  • 外贸网站建设浩森宇特用手机看网站源代码