以libev替代epoll,监听多路io的方法,以同时监听tcp连接和cmd命令行输入两个阻塞IO的方法为例如下:
#include <stdio.h>
#include <string.h>
#include <sys/unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<errno.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include <ev.h>
int sock;
void net_io_action(struct ev_loop *main_loop,ev_io*io_w,int e)
{
struct sockaddr_in cliaddr;
socklen_t len = sizeof(cliaddr);
int connfd = accept(sock, (struct sockaddr*) &cliaddr.sin_addr.s_addr, &len);
printf("New Connect: %d\n",connfd);
char* str="hello and bye!\n";
write(connfd,str,strlen(str));
close(connfd);
}
void io_action(struct ev_loop *main_loop,ev_io *io_w,int e)
{
int rst;
char buf[1024];
memset(buf,0,sizeof(buf));
puts("In std IO action");
read(STDIN_FILENO,buf,sizeof(buf));
buf[1023]='\0';
printf("String: %s\n",buf);
if(strcmp("q\n",buf) == 0)
{
ev_break(main_loop,EVBREAK_ALL);
printf("exit program\n");
}
}
void net_set()
{
sock=socket(AF_INET,SOCK_STREAM,0);
if(sock<0)
{
printf("socket()\n");
}
struct sockaddr_in server_socket;
struct sockaddr_in socket;
bzero(&server_socket,sizeof(server_socket));
server_socket.sin_family=AF_INET;
server_socket.sin_addr.s_addr=htonl(INADDR_ANY);
server_socket.sin_port=htons(6666);
if(bind(sock,(struct sockaddr*)&server_socket,sizeof(struct sockaddr_in))<0)
{
printf("bind() failed\n");
close(sock);
return;
}
if(listen(sock,10)<0)
{
printf("listen() failed\n");
close(sock);
return;
}
printf("success\n");
}
int main(int argc,char **argv) //failed to read mul-io, error fd.
{
ev_io io_w;
ev_io net_io_w;
struct ev_loop *main_loop = ev_default_loop(0);
net_set();
ev_init(&io_w,io_action);
ev_init(&net_io_w,net_io_action);
ev_io_set(&io_w,STDIN_FILENO,EV_READ); //fd is STDIN_FILENO
ev_io_set(&net_io_w,sock,EV_READ); //fd is socket fd
ev_io_start(main_loop,&io_w);
ev_io_start(main_loop,&net_io_w);
ev_run(main_loop,0);
close(sock);
return 0;
}
其中
net_io_action是tcp的连接监听IO,阻塞的是accept函数。
io_action是cmd命令行的输入监听IO,阻塞的是read函数。
net_set是socket的初始化,bind和listen,监听的是6666端口。
注意的是
ev_io_set的第二个参数,要区分不同的文件描述符,包括默认的STDIN_FILENO和sock的fd。