初識Libevent
libevent是用c寫的高並發網絡io庫,只要有文件描述符,就都可使用libevent。
libevent使用回調函數(callback) 。
有了libevent,網絡編程我有
1, FIFO的進程間通信。
利用FIFO的進程間通信read端:
#include <event2/event.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define MYFIFO "myfifo"
//call back
void readcb(evutil_socket_t fd, short what, void* arg){
//read fifo
char buf[24] = {0};
int len = read(fd, buf, sizeof(buf));
buf[len] = '\0';
printf("data len = %d, buf = %s\n", len, buf);
printf("read event:%s\n", what & EV_READ ? "Yes" : "No");
}
int main(){
unlink(MYFIFO);
mkfifo(MYFIFO, 0664);
int fd = open(MYFIFO, O_RDONLY | O_NONBLOCK);
//int fd = open(MYFIFO, O_RDONLY);
struct event_base* base;
base = event_base_new();
//create event
struct event* ev = NULL;
ev = event_new(base, fd, EV_READ | EV_PERSIST | EV_ET, readcb, NULL);
//add event
event_add(ev, NULL);
//start
event_base_dispatch(base);
//free event
event_free(ev);
event_base_free(base);
close(fd);
return 0;
}
利用FIFO的進程間通信write端:
#include <event2/event.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#define MYFIFO "myfifo"
//call back
void writecb(evutil_socket_t fd, short what, void* arg){
//write fifo
char buf[24] = {0};
static int num = 0;
sprintf(buf, "num = %d", num++);
write(fd, buf, strlen(buf) + 1);
}
int main(){
int fd = open(MYFIFO, O_WRONLY | O_NONBLOCK);
struct event_base* base;
base = event_base_new();
//create event
struct event* ev = NULL;
ev = event_new(base, fd, EV_WRITE | EV_PERSIST | EV_ET, writecb, NULL);
//add event
event_add(ev, NULL);
//start
event_base_dispatch(base);
//free event
event_free(ev);
event_base_free(base);
close(fd);
return 0;
}
2, socket通信。
server端:
#include <event2/event.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <event2/bufferevent.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <event2/listener.h>
//write callback
void write_cb(struct bufferevent* bev, void* ctx){
printf("all is sent\n");
}
//read callback
void read_cb(struct bufferevent *bev, void *ctx){
char buf[64];
size_t ret = bufferevent_read(bev, buf, sizeof(buf));
buf[ret] = '\0';
printf("server recf:%s\n", buf);
bufferevent_write(bev, "hahaha", 6);
}
//event callback
void event_cb(struct bufferevent *bev, short what, void *ctx){
if(what & BEV_EVENT_EOF){
printf("EOF\n");
}
if(what & BEV_EVENT_CONNECTED){
printf("connected\n");
}
}
//listener call back
void listencb(struct evconnlistener* listener, evutil_socket_t fd,
struct sockaddr* cli, int len, void* ptr){
struct event_base* base = evconnlistener_get_base(listener);
struct bufferevent* bev =
bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
//set callback function
bufferevent_setcb(bev, read_cb, write_cb, event_cb, NULL);
bufferevent_enable(bev, EV_READ | EV_WRITE);
//set water
bufferevent_setwatermark(bev, EV_READ, 10, 0);
bufferevent_setwatermark(bev, EV_WRITE, 1, 2);
}
int main(int argc, char** argv){
int port = atoi(argv[1]);
struct event_base* base;
base = event_base_new();
if(!base){
perror("event_base_new");
exit(1);
}
struct sockaddr_in s;
s.sin_family = AF_INET;
s.sin_port = htons(port);
s.sin_addr.s_addr = htonl(INADDR_ANY);
struct evconnlistener* listener =
evconnlistener_new_bind(base, listencb, NULL, LEV_OPT_CLOSE_ON_FREE,
-1, (struct sockaddr*)&s, sizeof(s));
if(!listener){
perror("bind");
exit(1);
}
event_base_dispatch(base);
event_base_free(base);
}
client端:
#include <event2/event.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <event2/bufferevent.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <event2/listener.h>
#include <event2/dns.h>
#include <stdlib.h>
#include <event2/util.h>
//read write callback
void readcb(struct bufferevent *bev, void *ctx){
char buf[64];
size_t ret = bufferevent_read(bev, buf, sizeof(buf));
buf[ret] = '\0';
printf("client recf:%s\n", buf);
}
//event callback
void eventcb(struct bufferevent *bev, short what, void *ctx){
if(what & BEV_EVENT_CONNECTED){
printf("connect okay\n");
}
else if(what & BEV_EVENT_ERROR){
struct event_base* base = ctx;
int err = bufferevent_socket_get_dns_error(bev);
if(err){
printf("DNS error:%s\n", evutil_gai_strerror(err));
}
printf("closing\n");
bufferevent_free(bev);
event_base_loopexit(base, NULL);
}
}
//terminal read callback
void termicb(evutil_socket_t fd, short what, void* ptr){
char buf[64] = {0};
int len = read(fd, buf, sizeof(buf));
buf[len] = '\0';
printf("in termicb\n");
struct bufferevent* bev = ptr;
bufferevent_write(bev, buf, len);
}
int main(int artc, char** argv){
struct event_base* base;
base = event_base_new();
struct evdns_base* dns_base;
dns_base = evdns_base_new(base, 1);
struct bufferevent* bev;
bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
int port = atoi(argv[2]);
bufferevent_setcb(bev, readcb, NULL, eventcb, base);
bufferevent_enable(bev, EV_READ);
bufferevent_socket_connect_hostname(bev, dns_base, AF_INET, argv[1], port);
struct event* ev = event_new(base, STDIN_FILENO, EV_READ | EV_PERSIST, termicb, bev);
event_add(ev, NULL);
event_base_dispatch(base);
event_base_free(base);
}