餐饮商家做网站的好处中国纪检监察报app下载
web/
2025/9/26 11:50:07/
文章来源:
餐饮商家做网站的好处,中国纪检监察报app下载,asp.net网站连接mysql,程序开发用什么软件一、网络IO基础
系统对象#xff1a; 网络IO涉及用户空间调用IO的进程或线程以及内核空间的内核系统。例如#xff0c;当进行read操作时#xff0c;会经历两个阶段#xff1a; 等待数据准备就绪。将数据从内核拷贝到进程或线程中。 多种网络IO模型的出现原因#xff1a;…一、网络IO基础
系统对象 网络IO涉及用户空间调用IO的进程或线程以及内核空间的内核系统。例如当进行read操作时会经历两个阶段 等待数据准备就绪。将数据从内核拷贝到进程或线程中。 多种网络IO模型的出现原因由于上述两个阶段的不同情况出现了多种网络IO模型。
二、阻塞IOblocking IO
特点 在Linux中默认所有socket都是阻塞的。以读操作为例当用户进程调用read系统调用kernel开始IO的第一阶段准备数据对于网络IO数据可能未到kernel要等待用户进程会被阻塞。直到kernel等到数据准备好将数据从kernel拷贝到用户内存并返回结果用户进程才解除阻塞状态。即阻塞IO在等待数据和拷贝数据两个阶段都阻塞进程。例如使用listen()、send()、recv()等接口构建服务器/客户机模型这些接口大多是阻塞型的。代码示例
// 创建服务器端的socket
int serverSocket socket(AF_INET, SOCK_STREAM, 0);
// 绑定地址
struct sockaddr_in serverAddr;
serverAddr.sin_family AF_INET;
serverAddr.sin_port htons(8080);
serverAddr.sin_addr.s_addr INADDR_ANY;
bind(serverSocket, (struct sockaddr*)serverAddr, sizeof(serverAddr));
// 监听连接
listen(serverSocket, 5);
// 接受连接
int clientSocket accept(serverSocket, NULL, NULL);
// 接收数据在此处进程会阻塞直到接收到数据或出错
char buffer[1024];
recv(clientSocket, buffer, sizeof(buffer), 0);
// 发送数据在此处进程也可能阻塞
send(clientSocket, buffer, strlen(buffer), 0);- 解释上述代码首先创建了一个服务器端的socket然后绑定地址和端口接着监听连接。当调用accept时如果没有连接请求会阻塞等待。一旦有连接调用recv接收数据时会阻塞直到有数据到达。发送数据时也可能阻塞例如网络拥堵或接收方接收缓冲区满。多线程/多进程改进方案 为解决单个连接阻塞影响其他连接的问题可在服务器端使用多线程或多进程。多线程可使用pthread_create()创建多进程使用fork()创建。多线程开销相对小适合为较多客户机服务进程更安全适合单个服务执行体需要大量CPU资源的情况。例如服务器端为多个客户机提供服务时可在主线程等待连接请求有连接时创建新线程或新进程提供服务。但当需要同时响应大量成百上千连接请求时多线程或多进程会严重占用系统资源导致系统效率下降和假死。
三、非阻塞IOnon-blocking IO
特点 通过设置socket为非阻塞如使用fcntl( fd, F_SETFL, O_NONBLOCK );。当用户进程发出read操作若kernel数据未准备好不会阻塞用户进程而是立即返回error。用户进程可根据返回结果判断数据是否准备好未准备好可再次发送read操作。当数据准备好kernel会将数据拷贝到用户内存并返回。例如recv()接口在非阻塞状态下调用后立即返回返回值有不同含义 recv()返回值大于 0表示接受数据完毕返回值是接收到的字节数。recv()返回 0表示连接正常断开。recv()返回 -1且errno等于EAGAIN表示recv操作未完成。recv()返回 - 1且errno不等于EAGAIN表示recv操作遇到系统错误errno。 代码示例
// 创建服务器端的socket
int serverSocket socket(AF_INET, SOCK_STREAM, 0);
// 设置为非阻塞
fcntl(serverSocket, F_SETFL, O_NONBLOCK);
// 绑定地址
struct sockaddr_in serverAddr;
serverAddr.sin_family AF_INET;
serverAddr.sin_port htons(8080);
serverAddr.sin_addr.s_addr INADDR_ANY;
bind(serverSocket, (struct sockaddr*)serverAddr, sizeof(serverAddr));
// 监听连接
listen(serverSocket, 5);
// 接受连接
int clientSocket accept(serverSocket, NULL, NULL);
// 接收数据此处不会阻塞会根据返回值判断状态
char buffer[1024];
int recvResult;
while ((recvResult recv(clientSocket, buffer, sizeof(buffer), 0)) -1 errno EAGAIN) {// 数据未准备好可进行其他操作或再次尝试接收
}
if (recvResult 0) {// 处理接收到的数据
} else if (recvResult 0) {// 连接断开
} else {// 其他错误
}- 解释在这个示例中将服务器端socket设置为非阻塞后调用recv时不会阻塞进程。如果recv返回-1且errno为EAGAIN说明数据还未准备好程序可继续执行其他操作或过段时间再尝试接收而不是像阻塞IO那样一直等待。四、多路复用IOIO multiplexing
特点 又称事件驱动IO(event driven IO)如select/epoll。单个进程可同时处理多个网络连接的IO基本原理是select/epoll函数不断轮询所负责的所有socket当某个socket有数据到达通知用户进程。流程用户进程调用select会被阻塞kernel监视select负责的socket当有socket数据准备好select返回用户进程再调用read操作将数据从kernel拷贝到用户进程。虽然使用select需要两个系统调用select和read但优势是可在一个线程内处理多个socket的IO请求。代码示例
#include stdio.h
#include sys/select.h
#include sys/socket.h
#include netinet/in.h
#include unistd.hint main() {int serverSocket socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in serverAddr;serverAddr.sin_family AF_INET;serverAddr.sin_port htons(8080);serverAddr.sin_addr.s_addr INADDR_ANY;bind(serverSocket, (struct sockaddr*)serverAddr, sizeof(serverAddr));listen(serverSocket, 5);fd_set readfds;FD_ZERO(readfds);FD_SET(serverSocket, readfds);int maxFd serverSocket;while (1) {fd_set tempFds readfds;int activity select(maxFd 1, tempFds, NULL, NULL, NULL);if (FD_ISSET(serverSocket, tempFds)) {int clientSocket accept(serverSocket, NULL, NULL);FD_SET(clientSocket, readfds);if (clientSocket maxFd) {maxFd clientSocket;}}for (int i 0; i maxFd; i) {if (FD_ISSET(i, tempFds) i! serverSocket) {char buffer[1024];int valread recv(i, buffer, 1024, 0);if (valread 0) {close(i);FD_CLR(i, readfds);} else {// 处理接收到的数据}}}}return 0;
}- 解释首先创建服务器socket绑定并监听。FD_ZERO和FD_SET用于初始化和设置文件描述符集合。select函数会阻塞等待集合中文件描述符的可读事件。当serverSocket有新连接时添加新连接的socket到集合并更新最大文件描述符。当其他socket可读时接收数据并处理。接口原型 FD_ZERO(int fd, fd_set* fds)初始化fd_set。FD_SET(int fd, fd_set* fds)将句柄添加到fd_set。FD_ISSET(int fd, fd_set* fds)检查句柄是否在fd_set中。FD_CLR(int fd, fd_set* fds)从fd_set中移除句柄。int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)用于探测多个文件句柄的状态变化readfds、writefds和exceptfds作为输入和输出参数可设置超时时间。 问题 当需要探测的句柄值较大时select()接口本身需要大量时间轮询很多操作系统提供更高效接口如epollLinux、kqueueBSD、/dev/pollSolaris等。该模型将事件探测和事件响应夹杂若事件响应执行体庞大会降低事件探测的及时性。可使用事件驱动库如libevent、libev库解决上述问题。
五、异步IOAsynchronous I/O
特点 Linux下的异步IO主要用于磁盘IO读写操作从内核2.6版本开始引入。用户进程发起read操作后可做其他事kernel收到asynchronous read后立刻返回不会阻塞用户进程。kernel等待数据准备完成将数据拷贝到用户内存完成后给用户进程发送信号通知。代码示例使用aio_read
#include aio.h
#include stdio.h
#include stdlib.h
#include unistd.h
#include fcntl.hvoid aio_completion_handler(union sigval sigval) {struct aiocb *req (struct aiocb *)sigval.sival_ptr;if (aio_error(req) 0) {char *buffer (char *)malloc(aio_return(req));// 处理读取到的数据free(buffer);}aio_destroy(req);
}int main() {int fd open(test.txt, O_RDONLY);if (fd 0) {perror(open);return 1;}struct aiocb my_aiocb;memset(my_aiocb, 0, sizeof(struct aiocb));my_aiocb.aio_fildes fd;my_aiocb.aio_buf malloc(1024);my_aiocb.aio_nbytes 1024;my_aiocb.aio_offset 0;my_aiocb.aio_sigevent.sigev_notify SIGEV_THREAD;my_aiocb.aaiocb.sigev_notify_function aio_completion_handler;my_aiocb.aio_sigevent.sigev_notify_attributes NULL;my_aiocb.aio_sigevent.sigev_value.sival_ptr my_aiocb;if (aio_read(my_aiocb) 0) {perror(aio_read);close(fd);return 1;}// 进程可做其他事情sleep(1);return 0;
}- 解释上述代码使用aio_read进行异步读操作。首先打开文件设置aiocb结构包含文件描述符、缓冲区、字节数等并设置信号通知方式和处理函数。调用aio_read后进程可以继续做其他事情当读操作完成会调用aio_completion_handler处理结果。重要性异步IO是真正非阻塞的对高并发网络服务器实现至关重要。
六、信号驱动IOsignal driven I/O SIGIO
特点 允许套接口进行信号驱动I/O并安装信号处理函数进程继续运行不阻塞。当数据准备好进程收到SIGIO信号可在信号处理函数中调用I/O操作函数处理数据。优势在于等待数据报到达期间进程可继续执行避免了select的阻塞与轮询。
七、服务器模型Reactor与Proactor
Reactor模型 是一种事件驱动机制用于同步I/O。应用程序将处理I/O事件的接口注册到Reactor上若相应事件发生Reactor调用注册的接口回调函数。三个重要组件 多路复用器如select、poll、epoll等系统调用。事件分发器将多路复用器返回的就绪事件分到对应的处理函数。事件处理器负责处理特定事件的处理函数。 具体流程 注册读就绪事件和相应事件处理器。事件分离器等待事件。事件到来激活分离器分离器调用事件对应的处理器。事件处理器完成实际的读操作处理数据注册新事件返还控制权。 优点响应快编程相对简单可扩展性和可复用性好。缺点当程序需要使用多核资源时会有局限因为通常是单线程的。代码示例
#include iostream
#include sys/epoll.h
#include sys/socket.h
#include netinet/in.h
#include unistd.h
#include fcntl.h
#include string.hclass EventHandler {
public:virtual void handleEvent(int fd) 0;
};class Reactor {
private:int epollFd;std::vectorEventHandler* handlers;
public:Reactor() {epollFd epoll_create1(0);}~Reactor() {close(epollFd);}void registerHandler(int fd, EventHandler* handler) {struct epoll_event event;event.data.fd fd;event.events EPOLLIN;epoll_ctl(epollFd, EPOLL_CTL_ADD, fd, event);handlers.push_back(handler);}void handleEvents() {struct epoll_event events[10];int numEvents epoll_wait(epollFd, events, 10, -1);for (int i 0; i numEvents; i) {int fd events[i].data.fd;for (EventHandler* handler : handlers) {handler-handleEvent(fd);}}}
};class EchoHandler : public EventHandler {
public:void handleEvent(int fd) override {char buffer[1024];int bytesRead recv(fd, buffer, sizeof(buffer), 0);if (bytesRead 0) {send(fd, buffer, bytesRead, 0);}}
};int main() {Reactor reactor;int serverSocket socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in serverAddr;serverAddr.sin_family AF_INET;serverAddr.sin_port htons(8080);serverAddr.sin_addr.s_addr INADDR_ANY;bind(serverSocket, (struct sockaddr*)serverAddr, sizeof(serverAddr));listen(serverSocket, 5);EchoHandler handler;reactor.registerHandler(serverSocket, handler);while (1) {reactor.handleEvents();}return 0;
}- 解释上述C代码中Reactor类负责创建epoll注册和处理事件。EventHandler是抽象基类EchoHandler是具体处理接收和发送的派生类。main函数创建服务器socket注册EchoHandler到Reactor并不断调用handleEvents处理事件。Proactor模型 最大特点是使用异步I/O所有I/O操作都交由系统的异步I/O接口执行工作线程只负责业务逻辑。具体流程 处理器发起异步操作并关注I/O完成事件。事件分离器等待操作完成事件。分离器等待时内核并行执行实际I/O操作并将结果存入用户缓冲区通知分离器读操作完成。I/O完成后通过事件分离器呼唤处理器。事件处理器处理用户缓冲区中的数据。 增加了编程复杂度但给工作线程带来更高效率可利用系统态的读写优化。在Windows上常用IOCP支持高并发Linux上因aio性能不佳主要以Reactor模型为主。也可使用Reactor模拟Proactor但在读写并行能力上会有区别。
八、同步I/O和异步I/O的区别总结
阻塞与非阻塞IO的区别 调用阻塞IO会阻塞进程直到操作完成非阻塞IO在kernel准备数据时会立刻返回。 同步与异步IO的区别 同步IO在做“IO operation”如read系统调用时会阻塞进程。阻塞IO、非阻塞IO、多路复用IO都属于同步IO。非阻塞IO在数据准备好时的拷贝数据阶段会阻塞进程而异步IO在整个过程中进程不会被阻塞进程发起IO操作后直接做其他事直到kernel发送信号通知完成。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/81537.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!