libevent(2) : 用libevent改写server端 实现echo_server

(1)  echo_server.c

listen_event的callback函数是 do_accept_cb

bev (buffer event)的三个callback函数:read_cb, write_cb, error_cb。 本例中,server端无需write_cb函数

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <errno.h>
#include <assert.h>

#include <event2/event.h>
#include <event2/bufferevent.h>

#define LISTEN_PORT 9999
#define LISTEN_BACKLOG 32

#define oops(msg) { perror(msg); exit(EXIT_FAILURE); }

void read_cb(struct bufferevent *bev, void *arg) {
	#define MAX_LINE    256
    char line[MAX_LINE+1];
    int n;
    evutil_socket_t fd = bufferevent_getfd(bev);

    while (n = bufferevent_read(bev, line, MAX_LINE), n > 0) {
        line[n] = '\0';
        printf("fd=%u, read line: %s\n", fd, line);

        bufferevent_write(bev, line, n);
    }
}

void write_cb(struct bufferevent *bev, void *arg) {}

void error_cb(struct bufferevent *bev, short event, void *arg) {
    evutil_socket_t fd = bufferevent_getfd(bev);
    printf("fd = %u, ", fd);
    if (event & BEV_EVENT_TIMEOUT) {
        printf("Timed out\n"); //if bufferevent_set_timeouts() called
    }
    else if (event & BEV_EVENT_EOF) {
        printf("connection closed\n");
    }
    else if (event & BEV_EVENT_ERROR) {
        printf("some other error\n");
    }
    bufferevent_free(bev);
}

void do_accept_cb(evutil_socket_t sockfd, short event_type, void *arg){
	evutil_socket_t fd;
	struct sockaddr_in sin;
	socklen_t slen;

	fd = accept(sockfd, (struct sockaddr *)&sin, &slen);
	if (fd < 0) oops("ERROR: accept: ");
	if (fd > FD_SETSIZE) oops("ERROR: fd > FD_SETSIZE");

	printf("ACCEPT: fd = %u\n", fd);

	struct event_base *base;
	base = (struct event_base *)arg;
	struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
	bufferevent_setcb(bev, read_cb, NULL, error_cb, arg);
	bufferevent_enable(bev, EV_READ|EV_WRITE|EV_PERSIST);
}

int main(int argc, char **argv){
	evutil_socket_t socket_fd;
	socket_fd = socket(PF_INET, SOCK_STREAM, 0);
	assert(socket_fd > 0);
	if(socket_fd == -1) oops("ERROR: socket initiate:");
	evutil_make_listen_socket_reuseable(socket_fd);

	struct sockaddr_in address;
	bzero((void *)&address, sizeof(address));
	address.sin_family = AF_INET;
	address.sin_addr.s_addr = inet_addr("172.16.166.129");
//	address.sin_addr.s_addr = 0;
	address.sin_port =  htons(LISTEN_PORT);

	int bind_return =  bind(socket_fd, (struct sockaddr *)&address, sizeof(address));
	if(bind_return == -1) oops("ERROR: bind:");

	int listen_return = listen(socket_fd, LISTEN_BACKLOG);
	if(listen_return == -1) oops("ERROR: listen:");

	//================================================
	puts("Listening...");
    evutil_make_socket_nonblocking(socket_fd);


    struct event_base *base;
    struct event *listen_event;

    base = event_base_new();
    assert(base != NULL);
    if(base == NULL) oops("ERROR: event_base_new() :");
    listen_event = event_new(base, socket_fd, EV_READ|EV_PERSIST, do_accept_cb, (void*)base);
    event_add(listen_event, NULL); //NULL: no timeout
    event_base_dispatch(base);

    puts("The End.");
	return 0;
}

(2) echo_client.c 

一个普通的client端,没有用libevent.

改进方法:可以设置buffer_event, 然后实现write_cb函数和error_cb函数。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>

#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include <arpa/inet.h>

#define oops(msg) { perror(msg); exit(EXIT_FAILURE); }
#define SIZE 256

#define LISTEN_PORT 9999

int main(){
        int socket_fd = socket(PF_INET, SOCK_STREAM, 0);
        if(socket_fd == -1) oops("socket initiating error...");


        struct sockaddr_in address;
        bzero(&address, sizeof(address));
        address.sin_family = AF_INET;
        address.sin_addr.s_addr = inet_addr("172.16.166.129");
//        address.sin_addr.s_addr = 0;
        address.sin_port =  htons(LISTEN_PORT);

        int connect_result = connect(socket_fd, (struct sockaddr*)&address, sizeof(address));
        if(connect_result == -1) oops("connect error...");

        char buffer[] = "hello world";
        ssize_t write_length = write(socket_fd, buffer, strlen(buffer)+1); //write to socket_fd
		if(write_length != (strlen(buffer)+1)) oops("error: write ...");


        ssize_t read_length = read(socket_fd, buffer, strlen(buffer)+1);
        if(read_length == -1) oops("error: read data from socket...");

        printf("the ret msg is: %s\n", buffer);

        close(socket_fd);
        return EXIT_SUCCESS;
}

3. Makefile.am

AM_CPPFLAGS = -I/usr/local/include

LDADD = -L/usr/local/lib -levent


bin_PROGRAMS = echo-server echo-client

echo_server_SOURCES = echo_server.c

echo_client_SOURCES = echo_client.c

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值