1. 程式人生 > >libevent基礎:用libevent寫服務端server程式和客戶端client程式

libevent基礎:用libevent寫服務端server程式和客戶端client程式

最近在進行一個基於libevent的專案,需要對libevent在socket通訊上的效能進行測試,寫了這個簡易的server和client程式,這也是libevent的基礎,希望對大家瞭解libevent有所幫助。

使用libevent-2.0.21。

server.c

/************************************
 * For msmr
 * server.c
 * tesing the speed of bufferevent_write
 * 2015-02-03
 * [email protected]
************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <event2/event.h>
#include <event2/listener.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <netinet/tcp.h>

static void server_on_read(struct bufferevent* bev,void* arg){
    struct timeval start_t;
    gettimeofday(&start_t,NULL);
    printf("Warning: server_on_read start timestamp  %lu.%06lu\n", start_t.tv_sec, start_t.tv_usec);
 
    struct evbuffer* input = bufferevent_get_input(bev);
    size_t len = 0;
    len = evbuffer_get_length(input);
    printf("There Is %u Bytes Data In The Buffer In Total.\n",
            (unsigned)len);
    
    // read
    char* buf;
    buf = (char*)malloc(sizeof(char)*len);
    if(NULL==buf){return;}
    //evbuffer_copyout(input,buf,len); // it do not clear the input buffer
    evbuffer_remove(input,buf,len); // clear the buffer
    printf("Server gets the message from client: %s\n", buf);    
   
    // check
    len = 0;
    len = evbuffer_get_length(input);
    printf("After the first reading, there Is %u Bytes Data Left In The Buffer.\n",
            (unsigned)len);
    
    free(buf);
    buf=NULL;
    return;
}


void server_on_accept(struct evconnlistener* listener,evutil_socket_t fd,struct sockaddr *address,int socklen,void *arg)
{
    printf("accept a client : %d\n", fd);

    // set TCP_NODELAY
    int enable = 1;
    if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*)&enable, sizeof(enable)) < 0)
        printf("Consensus-side: TCP_NODELAY SETTING ERROR!\n");

    struct event_base *base = evconnlistener_get_base(listener);
    struct bufferevent* new_buff_event = bufferevent_socket_new(base,fd,BEV_OPT_CLOSE_ON_FREE);
    // bufferevent_setwatermark(new_buff_event, EV_READ, 72, 0);
    bufferevent_setcb(new_buff_event,server_on_read,NULL,NULL,NULL);
    // set a read timeout of 1000 us
    // struct timeval tv = {0, 10000};
    // bufferevent_set_timeouts(new_buff_event, &tv, NULL);
    bufferevent_enable(new_buff_event,EV_READ|EV_WRITE);

    return;
}

int main()
{
    int port = 9876;
    struct sockaddr_in my_address;
    memset(&my_address, 0, sizeof(my_address));
    my_address.sin_family = AF_INET;
    my_address.sin_addr.s_addr = htonl(0x7f000001); // 127.0.0.1
    my_address.sin_port = htons(port);

    struct event_base* base = event_base_new();
    struct evconnlistener* listener = 
        evconnlistener_new_bind(base,server_on_accept,
                NULL,LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE,-1,
                (struct sockaddr*)&my_address,sizeof(my_address));

    if(!listener)
        exit(1);

    event_base_dispatch(base);
    evconnlistener_free(listener);
    event_base_free(base);
 
    return 0;
}



client.c

/************************************
 * For msmr 
 * server.c
 * tesing the speed of bufferevent_write
 * 2015-02-03
 * [email protected]
************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <event2/event.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <netinet/tcp.h>

int main()
{
    // build the message to be sent
    int length = 800; // the size of message
    char* mesg = (char*)malloc((length+1)*sizeof(char)); // Look out the end mark '/0' of a C string
    if (mesg == NULL)
        exit(1);
    int i;
    for (i=0; i<length; i++) 
        strcat(mesg, "a");

    printf("%s\n", mesg);
    printf("%d\n", (int)strlen(mesg));

    // build socket
    int port = 9876;
    struct sockaddr_in my_address;
    memset(&my_address, 0, sizeof(my_address));
    my_address.sin_family = AF_INET;
    my_address.sin_addr.s_addr = htonl(0x7f000001); // 127.0.0.1
    my_address.sin_port = htons(port);

    // build event base
    struct event_base* base = event_base_new();

    // set TCP_NODELAY to let data arrive at the server side quickly
    evutil_socket_t fd;
    fd = socket(AF_INET, SOCK_STREAM, 0);
    struct bufferevent* conn = bufferevent_socket_new(base,fd,BEV_OPT_CLOSE_ON_FREE);
    int enable = 1;
    if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*)&enable, sizeof(enable)) < 0)
       printf("ERROR: TCP_NODELAY SETTING ERROR!\n");
    //bufferevent_setcb(conn, NULL, NULL, NULL, NULL); // For client, we don't need callback function
    bufferevent_enable(conn, EV_WRITE);
    if(bufferevent_socket_connect(conn,(struct sockaddr*)&my_address,sizeof(my_address)) == 0)
            printf("connect success\n");

    // start to send data
    bufferevent_write(conn,mesg,length);
    // check the output evbuffer
    struct evbuffer* output = bufferevent_get_output(conn);
    int len = 0;
    len = evbuffer_get_length(output);
    printf("output buffer has %d bytes left\n", len);
 
    event_base_dispatch(base);

    free(mesg);
    mesg = NULL;

    bufferevent_free(conn);
    event_base_free(base);

    printf("Client program is over\n");

    return 0;
}


Makefile:

#! /bin/bash
.PHONY:clean

default:
	gcc -O server.c -o server -levent
	gcc -O client.c -o client -levent

clean:
	rm server client 


附上一個更好的牛人寫的例子:

https://github.com/bluecloudmatrix/recipes/tree/master/pingpong/libevent

相關推薦

libevent基礎libevent服務server程式客戶client程式

最近在進行一個基於libevent的專案,需要對libevent在socket通訊上的效能進行測試,寫了這個簡易的server和client程式,這也是libevent的基礎,希望對大家瞭解libevent有所幫助。 使用libevent-2.0.21。 server.c

PC軟體開發技術之二C#開發基於自動化介面的OPC客戶

OPC全稱是Object Linking and Embedding(OLE) for Process Control,它的出現為基於Windows的應用程式和現場過程控制應用建立了橋樑。OPC作為一整套介面、屬性和方法的協議標準集,與具體的開發語言沒有關係。 1、OPC客戶端介面方式

Python的基於Tkinter 的FTP客戶

# -*- coding: utf-8 -*- from ftplib import FTP import os from Tkinter import * from tkFileDialog import * class FTP_Tkinter():

服務腳本客戶腳本

參考 ngx 新頁面 定性 網絡 jsp 創建 結構 比較 (一)腳本、腳本語言 腳本(Script)是使用一種特定描述性語言、依據一定的格式編寫的可執行文件,又稱作宏或批處理文件。通俗地講,其實腳本是由一系列的bind和alias等命令的集合,如同一般的程序,腳

服務跳轉客戶跳轉

服務 res 訪問 url 客戶端 http 跳轉 客戶 新的 1 服務器端跳轉 客戶端想要訪問的內容不在該服務器上,該服務器自己去另外的服務器請求到該內容,然後還是由該服務器將內容返回給客戶端。 2 客戶端跳轉 客戶端想要訪問的內容不在該服務器上,該服務器告訴客戶端要去哪

ftp服務搭建腳本客戶ftp自動上傳腳本

被動模式 rgb fault virt otto shadow bak 安裝腳本 ssa linux服務器搭建ftp服務腳本(在centos6.5和centos7上測試通過)(該腳本沒有進行判斷,需要自行清理環境)(該腳本只允許上傳不允許下載,不允許使用匿名用戶和本地用戶登

Vue來進行移動Hybrid開發客戶間資料傳輸的一種方法

如果大家覺得有用,更多的模組請點選檢視 即上一篇Vue 頁面狀態保持頁面間資料傳輸的一種方法,今天我們說說我們團隊是怎麼和客戶端進行互動。 為什麼到了今天,還要提hybrid開發,就我所在團隊從中獲得的好處有: 團隊較小、業務較重、迭代頻繁、需要緊急響應的團隊和專案比較適合用 使用單頁應用技術

linux下多執行緒實現socket伺服器客戶的非同步通訊

前面介紹了用select函式來實現socket的非同步收發資料,但是select函式也有一些缺陷,要使socket能持續地通訊,select必須不停地檢測,這樣程序就會一直阻塞在這裡,限制了功能的擴充套件,這裡我們用多執行緒的方式,另建立兩個執行緒用來發送/接收

JSP-服務跳轉客戶跳轉

和Servlet的跳轉一樣,JSP的跳轉也分服務端跳轉和客戶端跳轉。首先準備 jump.jsp 首先準備一個jump.jsp 來分別演示客戶端跳轉和服務端跳轉客戶端跳轉 jsp的客戶端跳轉和Servlet中是一樣的。r

伺服器負載均衡客戶負載均衡的區別?

伺服器端負載均衡:例如Nginx,通過Nginx進行負載均衡,先發送請求,然後通過負載均衡演算法,在多個伺服器之間選擇一個進行訪問;即在伺服器端再進行負載均衡演算法分配。客戶端負載均衡:例如spring cloud中的ribbon,客戶端會有一個伺服器地址列表,在傳送請求前通

Swift服務 — Perfect框架

用Swift寫服務端 — Perfect框架學習(一) 一、Perfect簡介 Perfect是一組完整、強大的工具箱、軟體框架體系和Web應用伺服器,可以在Linux、iOS和macOS (OS X)上使用。該軟體體系為Swift工程師量身定製了一整套用於開發輕量、易維護、規模可擴充套

Swift服務 — Perfect框架學習(一)

// // DataBaseManager.swift // PerfectTemplatePackageDescription // // Created by ZFJ on 2018/1/17. // import MySQL //MARK: 資料庫資訊 let mysql_host = "12

libevent學習之三簡單的伺服器客戶

1.伺服器#include <stdio.h> #include <time.h> #include <event2/bufferevent.h> #include <event2/buffer.h> #include <

qttcp服務客戶介面遇到的問題及解決方法

問題1 #include <QTcpSocket> #include <QtcpServer> 在包含這兩個標頭檔案時提示找不到檔案 此時需要在此工程的.pro檔案中新增 QT += network 問題2 服務端的ui介

JAVA一個阿裏雲VPC Open API調程序

外部jar包 ef7 dac java 方式 命令 pro ng- 自動化管理 用JAVA寫一個阿裏雲VPC Open API調用程序 摘要:用JAVA拼出來Open API的URL 引言 VPC提供了豐富的API接口,讓網絡工程是可以通過API調用的方式

Java併發程式設計AQS一把可重入鎖

前一篇部落格Java併發程式設計:自己動手寫一把可重入鎖詳述瞭如何用synchronized同步的方式來實現一把可重入鎖,今天我們來效仿ReentrantLock類用AQS來改寫一下這把鎖。要想使用AQS為我們服務,首先得弄懂三個問題:AQS是什麼?AQS已經做了什麼以及我們還需要做些什

從零開始學Socket(二)連線服務客戶

先了解一下執行緒問題,在Main函式裡就是主執行緒他能處理程式碼,而new Thread就是新開一個執行緒,他和主執行緒互不干預,但是主執行緒完了,他也完了。他完了,主執行緒沒事。   在上篇部落格裡,我們已經建立好了伺服器端和客戶端,但是他們倆還沒有聯絡,要把他們聯絡起來,就

從零開始學Socket(一)服務客戶建立

上篇我提到Socket是TCP/IP的抽象介面。所以我們直接使用就好,沒必要知其甚解。 1.開啟VS 新建專案 名稱,位置隨意 這裡名稱是Server 框架選.NET 4.5(在這篇部落格裡也無所謂) 注意引用 using System.Net; using

No.23 經典筆試題(一)巨集來計算偏移量,判斷大小(聯合體法,指標法)

寫一個巨集,計算結構體中某變數相對於首地址的偏移,並給出說明 判斷大小端 程式碼1: //寫一個巨集,計算結構體中某變數相對於首地址的偏移,並給出說明 //定義的這個巨集將結構體裡邊的變數的地址取出後再強轉成char型,然後進行相減。 //注意:&s ==

【JVM第八篇】Java併發程式設計AQS一把可重入鎖

前一篇部落格Java併發程式設計:自己動手寫一把可重入鎖詳述瞭如何用synchronized同步的方式來實現一把可重入鎖,今天我們來效仿ReentrantLock類用AQS來改寫一下這把鎖。要想使用AQS為我們服務,首先得弄懂三個問題:AQS是什麼?AQS已經做了什麼以及我們還需要做些什麼?