検索
ホームページphp教程php手册Windows環境にシンプルなlibeventサーバーを実装する

私は Windows システムを使用しているため、最近 Libevent を学習し始めました。残念ながら、VS で参照できるプログラムはほとんどありません。たくさんのブログ記事を参考にした結果。私は簡単な Libevent Server プログラムを調査して作成しました。そして、インターネット上で簡単なクライアント プログラムを見つけ、コードのテストに成功しました。今日はここにメモしておきます。

Libevent は確かに非常に便利なもので、将来的には Windows 上で Libevent のマルチスレッドを実装する予定です。今日は参考のために私が作成したものを投稿します。コンパイルされ、vs2015 に渡されました。

デフォルトではシングルスレッドです (必要に応じてマルチスレッドとして構成できます)。各スレッドには structevent_base 構造体 (およびそれに接続されたイベント マネージャー) に対応する 1 つだけのイベント ベースがあります。 、一連のイベントをホストするためにスケジュールによって使用され、オペレーティング システムのプロセス管理と比較できます。もちろん、それはより単純です。イベントが発生すると、event_base は、イベントにバインドされた関数を適切なタイミング (必ずしも直ちにではありません) に呼び出します (いくつかの事前定義されたパラメーターとバインド中に指定されたパラメーターを渡します)。関数が実行された後は、他のイベントのスケジュール。

//event_base を作成します

structevent_base *base =event_base_new();

assert(base != NULL);

event_base 内には、epoll / kqueue などのシステム コールをブロックするループがあります。 、1 つまたはいくつかのイベントが発生するまで、その後これらのイベントを処理します。もちろん、これらのイベントはこのevent_baseにバインドされている必要があります。各イベントは struct イベントに対応し、fd または POSIX セマフォをリッスンできます (ここでは fd についてのみ説明します。その他についてはマニュアルを参照してください)。 structeven は、event_new を使用して作成およびバインドし、event_add を使用して有効にします:

//イベントを作成してバインドします

structevent *listen_event;

//パラメータ:event_base、listen fd、イベントのタイプと属性、バインドコールバック関数、コールバック関数に与えられるパラメータ

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

//パラメータ:event, timeout (struct timeval Type ) EV_TIMEOUT : タイムアウト

(b) EV_READ: ネットワークバッファにデータがある限り、コールバック関数がトリガーされます

(c) EV_WRITE: ネットワークバッファに送信されたデータが書き込まれている限り、コールバック関数はトリガーされますトリガーされる

(d) EV_SIGNAL: POSIX セマフォ、マニュアルを参照

(e) EV_PERSIST: この属性が指定されていない場合、コールバック関数がトリガーされた後にイベントが削除されます

(f) EV_ET: エッジ -エッジ トリガーをトリガーします。EPOLL_ET を参照してください

次に、発生するイベントの処理を開始できるように、event_base ループを開始する必要があります。イベントベースのディスパッチはループ内で開始され、ループは注意が必要なイベントがなくなるか、event_loopbreak() /event_loopexit() 関数が検出されるまで継続します。

//イベントループを開始します

event_base_dispatch(base);

次に、イベントにバインドされたコールバック関数 callback_func に注目します。それに渡されるのは、ソケット fd、イベントタイプと属性 bit_field、およびevents_new に渡される 最後のパラメータ (上記の行に戻って確認すると、event_base が渡されます。実際には、構造体を割り当て、関連するすべてのデータを入れて、それを取得できるevent_new にスローすることが重要です。ここ)。そのプロトタイプは次のとおりです:

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

サーバーの場合、上記のプロセスは次のように大まかに組み合わされます:

1. bind()、listen()、nonblocking の設定 (fcntl 設定は POSIX システムで使用でき、Windows を設定する必要はありません。

実際には libevent は統合パッケージ evutil_make_socket_nonblocking を提供します)

2.event_base を作成します

3.イベント、ソケットをevent_baseにホストし、監視するイベントタイプを指定し、対応するコールバック関数(およびそれに与える必要があるパラメータ)をバインドします

    。对于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:回复内容]

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

PhpStorm Mac バージョン

PhpStorm Mac バージョン

最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

VSCode Windows 64 ビットのダウンロード

VSCode Windows 64 ビットのダウンロード

Microsoft によって発売された無料で強力な IDE エディター