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

Table of Contents
回復(fù)內(nèi)容:
Home php教程 php手冊 Implement a simple libevent server in Windows environment

Implement a simple libevent server in Windows environment

Oct 19, 2016 am 10:19 AM

 I recently started learning Libevent because I am using a Windows system. Unfortunately, there are very few programs that can be referenced under VS. After referring to many blog articles. I explored and wrote a simple Libevent Server program. I also found a simple client program online and tested the code successfully. Make a note here today.

Libevent is indeed a very useful thing, and I am still learning. In the future, I will implement multi-threading of Libevent under windows. Today I will post what I have created for your reference only. Compiled and passed on vs2015.

It is single-threaded by default (can be configured as multi-threaded, if necessary). Each thread has one and only one event base, corresponding to a struct event_base structure (and the event manager attached to it) ), used by the schedule to host a series of events to it, can be compared to the process management of the operating system, of course, it is simpler. When an event occurs, event_base will call the function bound to the event at the appropriate time (not necessarily immediately) (passing in some predefined parameters, as well as a parameter specified when binding), until this After the function is executed, return to the schedule for other events.

//Create an event_base

struct event_base *base = event_base_new();

assert(base != NULL);

There is a loop inside event_base, which blocks system calls such as epoll / kqueue , until one/some events occur, and then handle these events. Of course, these events must be bound to this event_base. Each event corresponds to a struct event, which can be listening to an fd or POSIX semaphore (only fd is discussed here, see the manual for others). struct event uses event_new to create and bind, use event_add to enable:

//Create and bind an event

struct event *listen_event;

//Parameters: event_base, listening fd, event type and attributes , the bound callback function, the parameters given to the callback function

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

//Parameters: event, timeout (struct timeval Type ) EV_TIMEOUT: Timeout

(b) EV_READ: As long as there is data in the network buffer, the callback function will be triggered

(c) EV_WRITE: As long as the data sent to the network buffer is written, the callback function will be triggered

(d) EV_SIGNAL: POSIX semaphore, refer to the manual

(e) EV_PERSIST: If this attribute is not specified, the event will be deleted after the callback function is triggered

(f) EV_ET: Edge - Trigger edge trigger, refer to EPOLL_ET

Then you need to start the event_base loop so that you can start processing the events that occur. The event base dispatch is started in the loop, and the loop will continue until there are no more events that need attention, or the event_loopbreak() / event_loopexit() function is encountered.

//Start the event loop

event_base_dispatch(base);

Next, focus on the callback function callback_func bound to the event: what is passed to it is a socket fd, an event type and attribute bit_field, and what is passed to event_new The last parameter (go back to the above lines to review, event_base is passed in. In fact, it is more about allocating a structure, putting all the relevant data in, and then throwing it to event_new, which can be obtained here). Its prototype is:

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

For a server, the above process is roughly combined like this:

1. listener = socket( ), bind(), listen(), set nonblocking (fcntl settings can be used in POSIX systems, windows do not need to be set,

Actually libevent provides a unified package evutil_make_socket_nonblocking)

2. Create an event_base

3. Create An event, host the socket to event_base, specify the event type to be monitored, and bind the corresponding callback function (and the parameters that need to be given to it)

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

4. 啟用該事件

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

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

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

/*接下來關(guān)注下綁定到event的回調(diào)函數(shù)callback_func:傳遞給它的是一個socket fd、一個event類型及屬性bit_field、以及傳遞給event_new的最后一個參數(shù)(去上面幾行回顧一下,把event_base給傳進(jìn)來了,實際上更多地是分配一個結(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?????//地址長度聲明?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     ////注冊一個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ā)起連接請求?????????*/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)容]

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

PHP Tutorial
1488
72