亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

目錄
回復(fù)內(nèi)容:
首頁 php教程 php手冊(cè) 在Windows環(huán)境下實(shí)作一個(gè)簡(jiǎn)單的libevent伺服器

在Windows環(huán)境下實(shí)作一個(gè)簡(jiǎn)單的libevent伺服器

Oct 19, 2016 am 10:19 AM

  最近再學(xué)習(xí)Libevent由於自己使用的是windows系統(tǒng),遺憾的是有關(guān)在vs下可以參考的程序少之又少。在參考了許多的部落格文章後。自己摸摸寫了一個(gè)簡(jiǎn)單的Libevent Server程式。並且在網(wǎng)路上找了一個(gè)簡(jiǎn)單的客戶端程序,測(cè)試該代碼成功。今天在此做一個(gè)記錄。

Libevent的確是一個(gè)非常好用的東西,還在繼續(xù)學(xué)習(xí)中,後續(xù)還要在windows下實(shí)作Libevent的多執(zhí)行緒使用。今天先把自己搞出來的東西貼上來,僅供學(xué)習(xí)參考。在vs2015上編譯通過。

?

  預(yù)設(shè)情況下是單線程的(可以配置成多線程,如果有需要的話),每個(gè)線程有且只有一event base,對(duì)應(yīng)一個(gè)struct event_base結(jié)構(gòu)(以及附於其上的事件管理器),用來schedule託管給它的一系列event,可以和作業(yè)系統(tǒng)的進(jìn)程管理類比,當(dāng)然,要更簡(jiǎn)單一點(diǎn)。當(dāng)一個(gè)事件發(fā)生後,event_base會(huì)在適當(dāng)?shù)臅r(shí)間(不一定是立即)去呼叫綁定在這個(gè)事件上的函數(shù)(傳入一些預(yù)先定義的參數(shù),以及在綁定時(shí)指定的一個(gè)參數(shù)),直到這個(gè)函數(shù)執(zhí)行完,再返回schedule其他事件。

?

//建立一個(gè)event_base

struct event_base *base = event_base_new();

assert(base != NULL);

?

/雜,直到有一個(gè)/ 一些事件發(fā)生,然後去處理這些事件。當(dāng)然,這些事件要被綁定在這個(gè)event_base上。每個(gè)事件對(duì)應(yīng)一個(gè)struct event,可以是監(jiān)聽一個(gè)fd或POSIX信號(hào)量之類(這裡只講fd了,其他的看manual吧)。 struct event使用event_new來建立和綁定,使用event_add來啟用:

?

//建立並綁定一個(gè)event

struct event *listen_event;

//參數(shù):event_base, 監(jiān)聽的屬性與監(jiān)聽的屬性,綁定的回呼函數(shù),給回呼函數(shù)的參數(shù)

?

listen_event = event_new(base, listener, EV_READ | EV_PERSIST, callback_func, (void*)base);

/參數(shù): *類型的,NULL表示無逾時(shí)設(shè)定)

event_add(listen_event, NULL);

?

注:libevent支援的事件及屬性包括(使用bitfield實(shí)現(xiàn),所以要用| 來讓它們合體)

(abitfield實(shí)現(xiàn),所以要用| 來讓它們合體)

(a ) EV_TIMEOUT: 逾時(shí)

(b) EV_READ : 只要網(wǎng)路緩衝中還有數(shù)據(jù),回呼函數(shù)就會(huì)被觸發(fā)

(c) EV_WRITE : 只要塞給網(wǎng)路緩衝的資料被寫完,回呼函數(shù)就會(huì)被觸發(fā)

(d) EV_SIGNAL : POSIX信號(hào)量,參考manual吧

(e) EV_PERSIST : 不指定這個(gè)屬性的話,回呼函數(shù)被觸發(fā)後事件會(huì)被刪除

(f) EV_ET : Edge - Trigger邊緣觸發(fā),參考EPOLL_ET

接著需要啟動(dòng)event_base的循環(huán),這樣才能開始處理發(fā)生的事件。迴圈的啟動(dòng)event base dispatch,迴圈將持續(xù),直到不再有需要關(guān)注的事件,或是遇到event_loopbreak() / event_loopexit()函式。

//啟動(dòng)事件循環(huán)

event_base_dispatch(base);

接下來關(guān)注下綁定到event的回調(diào)函數(shù)callback_func:傳遞給它的是一個(gè)socket fd、一個(gè)event類型及屬性bit_field、以及傳遞給event_new的最後一個(gè)參數(shù)(去上面幾行回顧一下,把event_base傳進(jìn)來了,實(shí)際上更多地是分配一個(gè)結(jié)構(gòu)體,把相關(guān)的資料都撂進(jìn)去,然後丟給event_new,在這裡就能取得到了)。其原型是:

typedef void(*event_callback_fn)(evutil_socket_t sockfd, short event_type, void *arg)

?

對(duì)於一個(gè)伺服器而言,上面的流程大概是這樣組合的:1 月

list ),bind(),listen(),設(shè)定nonblocking(POSIX系統(tǒng)中可使用fcntl設(shè)置,windows不需要設(shè)置,

??? 實(shí)際上libevent提供了統(tǒng)一的包裝evutil_make_socket_nonblocking)

2. 建立一個(gè)一個(gè)event,將該socket託管給event_base,指定要監(jiān)聽的事件類型,並綁定上對(duì)應(yīng)的回呼函數(shù)(及需要給它的參數(shù))

??? 。對(duì)于listener socket來說,只需要監(jiān)聽EV_READ | EV_PERSIST

4. 啟用該事件

5. 進(jìn)入事件循環(huán)

-------------- -

6. (異步)當(dāng)有client發(fā)起請(qǐng)求的時(shí)候,調(diào)用該回調(diào)函數(shù),進(jìn)行處理。

/*接下來關(guān)注下綁定到event的回調(diào)函數(shù)callback_func:傳遞給它的是一個(gè)socket fd、一個(gè)event類型及屬性bit_field、以及傳遞給event_new的最后一個(gè)參數(shù)(去上面幾行回顧一下,把event_base給傳進(jìn)來了,實(shí)際上更多地是分配一個(gè)結(jié)構(gòu)體,把相關(guān)的數(shù)據(jù)都撂進(jìn)去,然后丟給event_new,在這里就能取得到了)。*/

?

服務(wù)器端代碼:Server.cpp

??1?#include??2?#include??3?#include??4?#include?<string.h>??5?#include??6?#include<event2/event.h>??7?#include??8?#include??9?#include?10?#pragma?comment?(lib,"ws2_32.lib")?11?#include?12?#define?LISTEN_PORT?9999?13?#define?LIATEN_BACKLOG?32?14?using?namespace?std;?15?/*********************************************************************************?16?*??????????????????????????????????????函數(shù)聲明?17?**********************************************************************************/?18?//accept回掉函數(shù)?19?void?do_accept_cb(evutil_socket_t?listener,?short?event,?void?*arg);?20?//read?回調(diào)函數(shù)?21?void?read_cb(struct?bufferevent?*bev,?void?*arg);?22?//error回調(diào)函數(shù)?23?void?error_cb(struct?bufferevent?*bev,?short?event,?void?*arg);?24?//write?回調(diào)函數(shù)?25?void?write_cb(struct?bufferevent?*bev,?void?*arg);?26?/*********************************************************************************?27?*??????????????????????????????????????函數(shù)體?28?**********************************************************************************/?29?//accept回掉函數(shù)?30?void?do_accept_cb(evutil_socket_t?listener,?short?event,?void?*arg)?31?{?32?????//傳入的event_base指針?33?????struct?event_base?*base?=?(struct?event_base*)arg;?34?????//socket描述符?35?????evutil_socket_t?fd;?36?????//聲明地址?37?????struct?sockaddr_in?sin;?38?????//地址長(zhǎng)度聲明?39?????socklen_t?slen?=?sizeof(sin);?40?????//接收客戶端?41?????fd?=?accept(listener,?(struct?sockaddr?*)&sin,?&slen);?42?????if?(fd?< 0) 43     { 44         perror("error accept"); 45         return; 46     } 47     printf("ACCEPT: fd = %u\n", fd); 48     ////注冊(cè)一個(gè)bufferevent_socket_new事件 49     struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE); 50     ////設(shè)置回掉函數(shù) 51     bufferevent_setcb(bev, read_cb, NULL, error_cb, arg); 52     ////設(shè)置該事件的屬性 53     bufferevent_enable(bev, EV_READ | EV_WRITE | EV_PERSIST); 54 } 55 ////read 回調(diào)函數(shù) 56 void read_cb(struct bufferevent *bev, void *arg) 57 { 58 #define MAX_LINE 256 59     char line[MAX_LINE + 1]; 60     int n; 61     //通過傳入?yún)?shù)bev找到socket fd 62     evutil_socket_t fd = bufferevent_getfd(bev); 63     // 64     while (n = bufferevent_read(bev, line, MAX_LINE)) 65     { 66         line[n] = &#39;\0&#39;; 67         printf("fd=%u, read line: %s\n", fd, line); 68         //將獲取的數(shù)據(jù)返回給客戶端 69         bufferevent_write(bev, line, n); 70     } 71 } 72 ////error回調(diào)函數(shù) 73 void error_cb(struct bufferevent *bev, short event, void *arg) 74 { 75     //通過傳入?yún)?shù)bev找到socket fd 76     evutil_socket_t fd = bufferevent_getfd(bev); 77     //cout << "fd = " << fd << endl; 78     if (event & BEV_EVENT_TIMEOUT) 79     { 80         printf("Timed out\n"); //if bufferevent_set_timeouts() called 81     } 82     else if (event & BEV_EVENT_EOF) 83     { 84         printf("connection closed\n"); 85     } 86     else if (event & BEV_EVENT_ERROR) 87     { 88         printf("some other error\n"); 89     } 90     bufferevent_free(bev); 91 } 92 ////write 回調(diào)函數(shù) 93 void write_cb(struct bufferevent *bev, void *arg) 94 { 95     char str[50]; 96     //通過傳入?yún)?shù)bev找到socket fd 97     evutil_socket_t fd = bufferevent_getfd(bev); 98     //cin >>?str;?99?????printf("輸入數(shù)據(jù)!");100?????scanf_s("%d",?&str);101?????bufferevent_write(bev,?&str,?sizeof(str));102?}103?104?int?main()105?{106?????int?ret;107?????evutil_socket_t?listener;108?????WSADATA??Ws;109?????//Init?Windows?Socket110?????if?(WSAStartup(MAKEWORD(2,?2),?&Ws)?!=?0)111?????{112?????????return?-1;113?????}114?????listener?=?socket(AF_INET,?SOCK_STREAM,?0);115?????assert(listener?>?0);116?????evutil_make_listen_socket_reuseable(listener);117?????struct?sockaddr_in?sin;118?????sin.sin_family?=?AF_INET;119?????sin.sin_addr.s_addr?=?0;120?????sin.sin_port?=?htons(LISTEN_PORT);121?????if?(bind(listener,?(struct?sockaddr?*)&sin,?sizeof(sin))?<?0)?{122?????????perror("bind");123?????????return?1;124?????}125?????if?(listen(listener,?1000)?<?0)?{126?????????perror("listen");127?????????return?1;128?????}129?????printf("Listening...\n");130?????evutil_make_socket_nonblocking(listener);131?????struct?event_base?*base?=?event_base_new();132?????assert(base?!=?NULL);133?????struct?event?*listen_event;134?????listen_event?=?event_new(base,?listener,?EV_READ?|?EV_PERSIST,?do_accept_cb,?(void*)base);135?????event_add(listen_event,?NULL);136?????event_base_dispatch(base);137?????printf("The?End.");138?????return?0;139?}

客戶端代碼:Client.cpp

?1?/*******?客戶端程序??client.c?************/?2?#define?_WINSOCK_DEPRECATED_NO_WARNINGS?3?#define?_CRT_SECURE_NO_WARNINGS?4?#include?5?#include?6?#include?7?#include?<string.h>???????
?8?#include?9?#include10?#include11?12?#pragma?comment?(lib,"ws2_32.lib")13?int?main(int?argc,?char?*argv[])14?{15?????WSADATA??Ws;16?????//Init?Windows?Socket17?????if?(WSAStartup(MAKEWORD(2,?2),?&Ws)?!=?0)18?????{19?????????return?0;20?????}21?????int?sockfd;22?????char?buffer[1024];23?????struct?sockaddr_in?server_addr;24?????struct?hostent?*host;25?????int?portnumber,?nbytes;26?27?????if?((host?=?gethostbyname("127.0.0.1"))?==?NULL)28?????{29?????????fprintf(stderr,?"Gethostname?error\n");30?????????exit(1);31?????}32?33?????if?((portnumber?=?atoi("9999"))<0)34     {35         fprintf(stderr, "Usage:%s hostname portnumber\a\n", argv[0]);36         exit(1);37     }38 39     /* 客戶程序開始建立 sockfd描述符  */40     if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)41     {42         fprintf(stderr, "Socket Error:%s\a\n", strerror(errno));43         exit(1);44     }45 46     /* 客戶程序填充服務(wù)端的資料       */47     memset(&server_addr,0, sizeof(server_addr));48     server_addr.sin_family = AF_INET;49     server_addr.sin_port = htons(portnumber);50     server_addr.sin_addr = *((struct in_addr *)host->h_addr);51?52?????/*?客戶程序發(fā)起連接請(qǐng)求?????????*/53?????if?(connect(sockfd,?(struct?sockaddr?*)(&server_addr),?sizeof(struct?sockaddr))?==?-1)54?????{55?????????fprintf(stderr,?"Connect?Error:%s\a\n",?strerror(errno));56?????????exit(1);57?????}58?59?????while?(true)60?????{61?????????char?MESSAGE[]?=?"hello?server..\n";62?????????//bufferevent_write(buf_ev,MESSAGE,strlen(MESSAGE));??
63?????????//??64?????????if?(-1?==?(::send(sockfd,?MESSAGE,?strlen(MESSAGE),?0)))65?????????{66?????????????printf("the?net?has?a?error?occured..");67?????????????break;68?????????}69?70?????????if?((nbytes?=?recv(sockfd,?buffer,?1024,0))?==?-1)71?????????{72?????????????fprintf(stderr,?"read?error:%s\n",?strerror(errno));73?????????????exit(1);74?????????}75?76?????????buffer[nbytes]?=?'\0';77?????????printf("I?have?received:%s\n",?buffer);78?????????memset(buffer,?0,?1024);79?80?????????Sleep(2);81?82?????}83?????/*?結(jié)束通訊?????*/84?????closesocket(sockfd);85?????exit(0);86?87?????return?0;88?}

?



回復(fù)內(nèi)容:

[db:回復(fù)內(nèi)容]

本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願(yuàn)投稿,版權(quán)歸原作者所有。本站不承擔(dān)相應(yīng)的法律責(zé)任。如發(fā)現(xiàn)涉嫌抄襲或侵權(quán)的內(nèi)容,請(qǐng)聯(lián)絡(luò)admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅(qū)動(dòng)的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強(qiáng)大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級(jí)程式碼編輯軟體(SublimeText3)

熱門話題

Laravel 教程
1597
29
PHP教程
1488
72