Linux下实现I/O复用的系统调用方式主要:select、poll、epoll。
select系统调用可在一段指定时间内,监听文件描述符上的可读、可写和异常等事件,判断发生的事件需要轮询。
#include <sys/select.h>
//select监听文件描述符事件
//nfds: 被监听文件描述符中最大值+1
//readfds: 可读事件对应的文件描述符集,对应位置1;会被内核修改,返回时无事件的置0。
//writefds: 可写事件对应的文件描述符集,对应位置1;会被内核修改,返回时无事件的置0。
//exceptfds:异常事件对应的文件描述符集,对应位置1;会被内核修改,返回时无事件的置0。
//timeout
//return: 返回就绪文件描述符中最大值+1
int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* timeout);
//fd_set比特向量操作
FD_ZERO(fd_set *fdset); //清楚fdset中所有比特位
FD_SET(int fd, fd_set *fdset); //设置fdset中比特位fd
FD_CLR(int fd, fd_set *fdset); //清除fdset中比特位fd
FD_ISSET(int fd, fd_set *fdset); //测试fdset中比特位fd是否被设置,用于判断是否有事件发生
socket可读
select可读(readfds)
socket可写(writefds)
socket异常(exceptfds)
poll系统调用与select类似,需要轮询判断监听文件描述符集上的事件,但没有监听文件描述符数量限制。
#include <poll.h>
//poll监听文件描述符上指定的事件
//fds: pollfd结构类型的数组
//nfds: pollfd数组长度
//return: 返回就绪文件描述符中最大值+1
int poll(struct pollfd* fds, nfds_t nfds, int timeout);
//pollfd结构体,描述文件描述符上的可读、可写、异常等事件
struct pollfd{
int fd; //文件描述符
short events; //注册的事件,一系列事件的按位或
short revents; //实际发生的事件,由内核填充,一些列事件的按位或
}
| 事件 | 描述 | 是否可作为输入 | 是否可作为输出 |
|---|---|---|---|
| POLLIN | 普通或优先数据可读 | 是 | 是 |
| POLLRDNORM | 普通数据可读 | 是 | 是 |
| POLLRDBAND | 优先级带数据可读(linux不支持) | 是 | 是 |
| POLLPRI | 高优先级数据可读,如TCP带外数据 | 是 | 是 |
| POLLOUT | 普通或优先数据可写 | 是 | 是 |
| POLLWRNORM | 普通数据可写 | 是 | 是 |
| POLLWRBAND | 优先级带数据可写 | 是 | 是 |
| POLLRDHUB | TCP连接被对方关闭,或者对方关闭了写操作。由GNU引入 | 是 | 是 |
| POLLERR | 错误 | 否 | 是 |
| POLLHUB | 挂起。比如管道的写端被关闭,读端描述符上将收到POLLHUB事件 | 否 | 是 |
| POLLNVAL | 文件描述符没有打开 | 否 | 是 |
epoll相比select更加高效,主要体现在:
使用epoll监听文件描述符时,有两种事件触发模式:
epoll在内核中使用事件表(红黑树)维护监听的文件描述符,并支持对事件表的增删改。
#include <sys/epoll.h>
//epoll事件结构体
strcut epoll_event{
_uint32_t events; //epoll事件
epoll_data_t data; //用户数据,包含监听的文件描述符信息
}
//用户数据联合体
typedef union epoll_data{
void* ptr; //指定与fd相关的用户数据,用户数据包含监听的文件描述符
int fd; //监听的文件描述符fd(常用)
uint32_t u32;
uint64_t u64;
} epoll_data_t;
//创建epoll内核事件表
//size: 提示内核需要的事件表多大
int epoll_create(int size);
//操作epoll内核事件表
//epfd: epoll内核事件表
//op: 参数指定操作,包括增(EPOLL_CTL_ADD)、删(EPOLL_CTL_DEL)、改(EPOLL_CTL_MOD)
//fd: 被操作的文件描述符
//event:事件
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
//监听事件表上文件描述符的事件
//epfd: epoll内核事件表
//events: 就绪事件数组,由内核修改
//maxevents:最多监听事件数
//timeout:
//return: 就绪文件描述符个数
int epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout);
epoll支持的时间类型和poll基本相同,表示epoll时间类型的宏实在poll对应的宏前加上‘E’,如EPOLLIN。
服务端代码功能:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
if (argc <= 2)
{
printf("usage: %s ip_address port_number\n", basename(argv[0]));
return 1;
}
const char *ip = argv[1];
int port = atoi(argv[2]);
printf("ip is %s and port is %d\n", ip, port);
int ret = 0;
struct sockaddr_in address;
bzero(&address, sizeof(address));
address.sin_family = AF_INET;
inet_pton(AF_INET, ip, &address.sin_addr);
address.sin_port = htons(port);
int listenfd = socket(PF_INET, SOCK_STREAM, 0);
assert(listenfd >= 0);
ret = bind(listenfd, (struct sockaddr *)&address, sizeof(address));
assert(ret != -1);
ret = listen(listenfd, 5);
assert(ret != -1);
struct sockaddr_in client_address;
socklen_t client_addrlength = sizeof(client_address);
int connfd = accept(listenfd, (struct sockaddr *)&client_address, &client_addrlength);
if (connfd < 0)
{
printf("errno is: %d\n", errno);
close(listenfd);
}
char remote_addr[INET_ADDRSTRLEN];
printf("connected with ip: %s and port: %d\n", inet_ntop(AF_INET, &client_address.sin_addr, remote_addr, INET_ADDRSTRLEN), ntohs(client_address.sin_port));
char buf[1024];
fd_set read_fds;
fd_set exception_fds;
FD_ZERO(&read_fds);
FD_ZERO(&exception_fds);
int nReuseAddr = 1;
setsockopt(connfd, SOL_SOCKET, SO_OOBINLINE, &nReuseAddr, sizeof(nReuseAddr));
while (1)
{
memset(buf, '\0', sizeof(buf));
FD_SET(connfd, &read_fds);
FD_SET(connfd, &exception_fds);
ret = select(connfd + 1, &read_fds, NULL, &exception_fds, NULL);
printf("select one\n");
if (ret < 0)
{
printf("selection failure\n");
break;
}
if (FD_ISSET(connfd, &read_fds))
{
ret = recv(connfd, buf, sizeof(buf) - 1, 0);
if (ret <= 0)
{
printf("can not read\n");
break;
}
printf("get %d bytes of normal data: %s\n", ret, buf);
}
else if (FD_ISSET(connfd, &exception_fds))
{
ret = recv(connfd, buf, sizeof(buf) - 1, MSG_OOB);
if (ret <= 0)
{
printf("can not read\n");
break;
}
printf("get %d bytes of oob data: %s\n", ret, buf);
}
}
close(connfd);
close(listenfd);
return 0;
}
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <poll.h>
int main(int argc, char *argv[])
{
if (argc <= 2)
{
printf("usage: %s ip_address port_number\n", basename(argv[0]));
return 1;
}
const char *ip = argv[1];
int port = atoi(argv[2]);
printf("ip is %s and port is %d\n", ip, port);
int ret = 0;
struct sockaddr_in address;
bzero(&address, sizeof(address));
address.sin_family = AF_INET;
inet_pton(AF_INET, ip, &address.sin_addr);
address.sin_port = htons(port);
int listenfd = socket(PF_INET, SOCK_STREAM, 0);
assert(listenfd >= 0);
ret = bind(listenfd, (struct sockaddr *)&address, sizeof(address));
assert(ret != -1);
ret = listen(listenfd, 5);
assert(ret != -1);
struct sockaddr_in client_address;
socklen_t client_addrlength = sizeof(client_address);
int connfd = accept(listenfd, (struct sockaddr *)&client_address, &client_addrlength);
if (connfd < 0)
{
printf("errno is: %d\n", errno);
close(listenfd);
}
char remote_addr[INET_ADDRSTRLEN];
printf("connected with ip: %s and port: %d\n", inet_ntop(AF_INET, &client_address.sin_addr, remote_addr, INET_ADDRSTRLEN), ntohs(client_address.sin_port));
char buf[1024];
pollfd poll_fds[1];
bzero(poll_fds, sizeof(poll_fds));
poll_fds[0].fd = connfd;
poll_fds[0].events = POLLIN;
int nReuseAddr = 1;
setsockopt(connfd, SOL_SOCKET, SO_OOBINLINE, &nReuseAddr, sizeof(nReuseAddr));
while (1)
{
memset(buf, '\0', sizeof(buf));
ret = poll(poll_fds, 1, -1);
printf("select one\n");
if (ret < 0)
{
printf("selection failure\n");
break;
}
if (poll_fds[0].events == POLLIN)
{
ret = recv(connfd, buf, sizeof(buf) - 1, 0);
if (ret <= 0)
{
printf("can not read\n");
break;
}
printf("get %d bytes of normal data: %s\n", ret, buf);
}
}
close(connfd);
close(listenfd);
return 0;
}
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/epoll.h>
int main(int argc, char *argv[])
{
if (argc <= 2)
{
printf("usage: %s ip_address port_number\n", basename(argv[0]));
return 1;
}
const char *ip = argv[1];
int port = atoi(argv[2]);
printf("ip is %s and port is %d\n", ip, port);
int ret = 0;
struct sockaddr_in address;
bzero(&address, sizeof(address));
address.sin_family = AF_INET;
inet_pton(AF_INET, ip, &address.sin_addr);
address.sin_port = htons(port);
int listenfd = socket(PF_INET, SOCK_STREAM, 0);
assert(listenfd >= 0);
ret = bind(listenfd, (struct sockaddr *)&address, sizeof(address));
assert(ret != -1);
ret = listen(listenfd, 5);
assert(ret != -1);
struct sockaddr_in client_address;
socklen_t client_addrlength = sizeof(client_address);
int connfd = accept(listenfd, (struct sockaddr *)&client_address, &client_addrlength);
if (connfd < 0)
{
printf("errno is: %d\n", errno);
close(listenfd);
}
char remote_addr[INET_ADDRSTRLEN];
printf("connected with ip: %s and port: %d\n", inet_ntop(AF_INET, &client_address.sin_addr, remote_addr, INET_ADDRSTRLEN), ntohs(client_address.sin_port));
char buf[1024];
//创建内核事件表
int epfd = epoll_create(10);
//注册事件
epoll_event event;
event.data.fd = connfd;
event.events = EPOLLIN;
epoll_ctl(epfd, EPOLL_CTL_ADD, connfd, &event);
//就绪事件数组
epoll_event events[10];
int nReuseAddr = 1;
setsockopt(connfd, SOL_SOCKET, SO_OOBINLINE, &nReuseAddr, sizeof(nReuseAddr));
while (1)
{
memset(buf, '\0', sizeof(buf));
ret = epoll_wait(epfd, events, 1, -1);
printf("select one\n");
if (ret < 0)
{
printf("errno: %d\n", errno);
printf("selection failure\n");
break;
}
if (events[0].events == EPOLLIN)
{
ret = recv(connfd, buf, sizeof(buf) - 1, 0);
if (ret <= 0)
{
printf("can not read\n");
break;
}
printf("get %d bytes of normal data: %s\n", ret, buf);
}
}
close(connfd);
close(listenfd);
return 0;
}
客户端代码功能:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
if (argc <= 2)
{
printf("usage: %s ip_address port_number\n", basename(argv[0]));
return 1;
}
const char *ip = argv[1];
int port = atoi(argv[2]);
struct sockaddr_in server_address;
bzero(&server_address, sizeof(server_address));
server_address.sin_family = AF_INET;
inet_pton(AF_INET, ip, &server_address.sin_addr);
server_address.sin_port = htons(port);
int sockfd = socket(PF_INET, SOCK_STREAM, 0);
assert(sockfd >= 0);
if (connect(sockfd, (struct sockaddr *)&server_address, sizeof(server_address)) < 0)
{
printf("connection failed\n");
}
else
{
printf("send oob data out\n");
const char *oob_data = "abc";
const char *normal_data = "123";
send(sockfd, normal_data, strlen(normal_data), 0);
send(sockfd, oob_data, strlen(oob_data), MSG_OOB);
send(sockfd, normal_data, strlen(normal_data), 0);
}
close(sockfd);
return 0;
}
一、网络环境及TOP1.1R1相当于内网的一台PC, IP:192.168.1.10 网关为 192.168.1.254[R1]iproute-static0.0.0.00192.168.1.254#R1配置默认路由(网关)1.2R2为出口路由器,分别连接内网R1及外网R31)R2 内网接口IP:192.168.1.2542)R2外网接口IP:100.1.1.102)R2NAT地址为:100.1.1.11-100.1.1.14二、静态NAT配置1.1静态NAT(一对一双向)R2配置静态NAT,将公网IP100.1.1.11映射到内网R1 192.168.1.10[R2]intg0/0/1[R2
VHDL程序结构:条件语句if_then_else_endif数据类型BIT类型(取逻辑位’1’或’0’)、整数类型INTEGER、布尔类型BOOLEAN(取TRUE或FALSE)、标准逻辑类型STD_LOGIC等进程语句与顺序语句process(敏感信号表)_endprocessVHDL中所有的顺序语句都必须放在进程语句中端口语句port(端口模式;端口数据类型);端口模式in:输入端口out:输出端口inout:双向端口buffer:缓冲端口关键字(不区分大小写)entity、architecture、end、if、else、in、out等;标识符(不区分大小写)自定义实体名、结构体名、端
我遵循以下链接中的示例:https://github.com/hakimel/reveal.js#multiplexing,但不知何故,多路复用不起作用——当母版幻灯片更新时,客户端不会更新。我已经在reveal.js演示socket.io服务器上进行了尝试,并尝试托管我自己的服务器。这些选项都不起作用,而且我很确定我已经正确配置了它们。这是我的配置代码:master/index.htmlReveal.initialize({controls:true,progress:true,history:true,center:true,multiplex:{id:'e2bc6e79f19fb
我们想用d3画一个网络路由图,起始节点和结束节点是固定的,但中间的路径不同,可能共享一些节点,例如:我阅读了来自Configurefixed-layoutstaticgraphind3.js的评论并成功创建了一个简单的图形,如:但是当我向图中添加更多节点时,它变得随机(刷新后不是静态的)并且不再是正交的:所以我的问题是:是否可以使用d3.js来绘制接近所需的东西图形?或者有没有我应该在我的工作中使用的算法图实现? 最佳答案 在这里看我的演示。http://jsfiddle.net/doraeimo/JEcdS/主要思想是基于树建立连
所以最近几天我一直在玩promises,只是想转换一些项目,使用promises,但是我遇到这个问题不止几次。在阅读文章和教程时,一切看起来都很流畅和干净:getDataFromDB().then(makeCalculatons).then(getDataFromDB).then(serveToClient)但实际上并非如此。程序有很多改变整个流程的“if条件”:getDataFromCache(data).then(function(result){if(result){returnresult;}else{returngetDataFromDB();}}).then(functio
我已经用了几个星期了,但似乎无法弄清楚如何绘制下面的多路径图表。Focus+ContextviaBrushingchart我试图创建一个jsfiddle,但无法复制我得到的屏幕。在这一点上,我所拥有的与原始图表相似,只是只有一条路径而不是区域,并且刷牙工作正常。基本上尝试结合焦点图和多系列折线图Multiserieschart.但是,当我尝试添加另一条路径时,没有任何效果。请提出我需要做出的任何想法或更改以使其正常工作。还有其他类似的图表(或图表示例)我可以看一下吗?可以以任何方式或形式重新排列数据以使其起作用。Jsfiddlepath{fill:none;stroke:white;s
Option"setupTestFrameworkScriptFile"wasreplacedbyconfiguration"setupFilesAfterEnv",whichsupportsmultiplepaths.Pleaseupdateyourconfiguration.我在这里找到了这个确切的问题:setupTestFrameworkScriptFileisnotsupportederror我将我的jest.config.js重命名为setUpTests.js但这并没有删除已弃用的错误警告。import{configure}from'enzyme'importAdapterf
我正在尝试了解同步事件多路分解如何成为繁忙等待的解决方案。假设有3个IO操作,我们有一段代码不断循环检查这3个操作中是否有数据可供读取。arry=[event1,event2,event3]while(arryisnotempty){for(i=0;i上面的伪代码做了一个忙碌的等待。现在,在同步事件多路分解或react器模式中,事件监听器会在事件发生时对其做出响应。但是事件监听器如何在不忙等待的情况下做到这一点? 最佳答案 进程是已执行的计算机程序的实例(执行任务或模块)。在一个进程中,我们可以有多个称为线程的组件。您可以将线程想象
码分复用一、简介二、CDMA原理2.1表示2.2如何选择码片序列正交的实现:三、流程图发送端接收端四、例题一、简介·码分复用简称CDM·可以实现多个用户同时使用同样频率进行通信·如何实现?——通过各用户的码序列进行区分。二、CDMA原理2.1表示1、每个比特(0或1)以一组码序列发送(m位编码将每位比特划分为m)码片:一个数据信号(如逻辑1或0)通常要用多个编码信号来进行编码,那么其中的一个编码信号就称为一个码片2、一个数据信号(如逻辑1或0)通常要用多个编码信号来进行编码,如这个站要发送1,就发送该码片的原码,如要发送0,就发送给码片的反码每个站都会分配一个码片序列,那么如何选择码片序列呢?
我的程序在每次一个连接的情况下运行良好,但在并发连接的情况下就不行。我需要由一个函数呈现所有连接,该函数将包含我在服务中需要的所有数据,但效果不佳,因此我用下面的简单代码进行了说明:packagemainimport("encoding/json""fmt""github.com/gorilla/mux""github.com/rs/cors""net/http""reflect""time")varOutstruct{Codeint`json:"status"`Message[]interface{}`json:"message"`}funcClear(vinterface{}){p