1. 程式人生 > >libevent2入門例-簡單的伺服器(也有簡短客戶端)

libevent2入門例-簡單的伺服器(也有簡短客戶端)

  libevent 庫實在是輕量級,下面用不到百行程式碼,實現一個簡單的伺服器,其功能是在9995埠監聽連線,有連線上來就給回覆:“Hello, World!”。另外還添加了一個訊號處理回撥,當你按 Ctrl+C 時,伺服器會清理資源,乾乾淨淨地退出,這是一個伺服器開發者必備素質:)

  客戶端就馬馬虎虎地寫一個了,只用到C標準庫就行。

  最後,還是提醒一下,都是linux程式設計,libevent對windows支援並不好,windows也不太需要開源網路庫,.Net中有豐富而強大的網路支援。

服務端程式碼 helloworld.c

0001#include <string.h>
0002#include <errno.h>
0003#include <stdio.h>
0004#include <signal.h>
0005#include <unistd.h>
0006
0007#include <event2/bufferevent.h>
0008#include <event2/buffer.h>
0009#include <event2/listener.h>
0010
0011staticconstchar MESSAGE[] ="Hello, World!\n";
0012staticconstint PORT = 9995;
0013
0014staticvoid listener_cb(struct evconnlistener *, evutil_socket_t, struct sockaddr *, int socklen, void*);
0015staticvoid signal_cb(evutil_socket_t, short, void*);
0016
0017int main(int argc, char**argv)
0018{
0019    struct event_base *base;
0020    struct evconnlistener *listener;
0021    struct event *signal_event;
0022
0023    struct sockaddr_in sin;
0024
0025    // 初始化 libevent,libevent2推薦使用 event_base_new(),因為fork後更好用
0026    base = event_base_new();
0027    if (!base) {
0028        fprintf(stderr, "Could not initialize libevent!\n");
0029        return 1;
0030    }
0031
0032    memset(&sin, 0, sizeof(sin));
0033    sin.sin_family = AF_INET;
0034    sin.sin_port = htons(PORT);
0035
0036    // 繫結到 ip:port 監聽
0037    listener = evconnlistener_new_bind(base, listener_cb, (void*)base,
0038        LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE, -1,
0039        (struct sockaddr*)&sin,
0040        sizeof(sin));
0041
0042    if (!listener) {
0043        fprintf(stderr, "Could not create a listener!\n");
0044        return 1;
0045    }
0046
0047    // 新增一個處理訊號的事件
0048    signal_event = evsignal_new(base, SIGINT, signal_cb, (void*)base);
0049
0050    if (!signal_event || event_add(signal_event, NULL)<0) {
0051        fprintf(stderr, "Could not create/add a signal event!\n");
0052        return 1;
0053    }
0054
0055    // 開工
0056    event_base_dispatch(base);
0057
0058    // 釋放已分配的資源(上面函式中用過 new 的)
0059    evconnlistener_free(listener);
0060    event_free(signal_event);
0061    event_base_free(base);
0062
0063    printf("done\n");
0064    return 0;
0065}
0066
0067// 監聽到有人連線,處理
0068staticvoid listener_cb(struct evconnlistener *listener, evutil_socket_t fd,
0069    struct sockaddr *sa, int socklen, void*user_data)
0070{
0071    struct event_base *base = user_data;
0072    struct bufferevent *bev;
0073
0074    bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
0075    if (!bev) {
0076        fprintf(stderr, "Error constructing bufferevent!");
0077        event_base_loopbreak(base);
0078        return;
0079    }
0080
0081    // 向客戶端傳送訊息 MESSAGE
0082    bufferevent_write(bev, MESSAGE, strlen(MESSAGE));
0083}
0084
0085staticvoid signal_cb(evutil_socket_t sig, short events, void*user_data)
0086{
0087    struct event_base *base = user_data;
0088    struct timeval delay = { 2, 0 };
0089
0090    printf("Caught an interrupt signal; exiting cleanly in two seconds.\n");
0091
0092    // 收工
0093    event_base_loopexit(base, &delay);
0094}
 

客戶端程式碼 client.c

0001#include <stdio.h>
0002#include <stdlib.h>
0003#include <errno.h>
0004#include <unistd.h>
0005#include <string.h>
0006#include <sys/socket.h>
0007#include <netinet/in.h>
0008#include <netdb.h>
0009
0010int main(int argc, char**argv)
0011{
0012    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
0013    struct hostent *server = gethostbyname("127.0.0.1");
0014    if (server == NULL) {
0015        printf("ERROR, no such host\n");
0016        exit(0);
0017    }
0018
0019    struct sockaddr_in serv_addr;
0020    memset((char*) &serv_addr, 0, sizeof(serv_addr));
0021
0022    serv_addr.sin_family = AF_INET;
0023    memcpy((char*)server->h_addr,
0024            (char*)&serv_addr.sin_addr.s_addr,
0025            server->h_length);
0026    serv_addr.sin_port = htons(9995);
0027    if (connect( sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0){
0028        printf("error connect:%d\n", errno);
0029        exit(0);
0030    }
0031
0032    char buf[1024]= {0};
0033    int n = read( sockfd, buf,sizeof(buf));
0034    buf[n]='\0';
0035    printf("%s\n", buf);
0036
0037    close(sockfd);
0038    return 0;
0039}