search
Homephp教程php手册Implement a simple libevent server in Windows environment

 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来说,只需要监听EV_READ | EV_PERSIST

4. 启用该事件

5. 进入事件循环

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

6. (异步)当有client发起请求的时候,调用该回调函数,进行处理。

/*接下来关注下绑定到event的回调函数callback_func:传递给它的是一个socket fd、一个event类型及属性bit_field、以及传递给event_new的最后一个参数(去上面几行回顾一下,把event_base给传进来了,实际上更多地是分配一个结构体,把相关的数据都撂进去,然后丢给event_new,在这里就能取得到了)。*/

 

服务器端代码:Server.cpp

  1 #include  2 #include  3 #include  4 #include <string.h>  5 #include  6 #include<event2>  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 *                                      函数声明 17 **********************************************************************************/ 18 //accept回掉函数 19 void do_accept_cb(evutil_socket_t listener, short event, void *arg); 20 //read 回调函数 21 void read_cb(struct bufferevent *bev, void *arg); 22 //error回调函数 23 void error_cb(struct bufferevent *bev, short event, void *arg); 24 //write 回调函数 25 void write_cb(struct bufferevent *bev, void *arg); 26 /********************************************************************************* 27 *                                      函数体 28 **********************************************************************************/ 29 //accept回掉函数 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 > str; 99     printf("输入数据!");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)) <p></p>
<p>客户端代码:Client.cpp</p>
<p class="cnblogs_code"></p>
<pre class="brush:php;toolbar:false"> 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"))h_addr);51 52     /* 客户程序发起连接请求         */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     /* 结束通讯     */84     closesocket(sockfd);85     exit(0);86 87     return 0;88 }</string.h>

 



回复内容:

[db:回复内容]

Statement
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

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.

Undress AI Tool

Undress AI Tool

Undress images for free

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

SublimeText3 Linux new version

SublimeText3 Linux new version

SublimeText3 Linux latest version

Dreamweaver Mac version

Dreamweaver Mac version

Visual web development tools

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

Powerful PHP integrated development environment

SecLists

SecLists

SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)