<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Ubuntu20.04 安裝 libevent

      https://blog.csdn.net/qq_62381297/article/details/136151148

      Ubuntu20.04 安裝 libevent

      文章目錄
      libevent 源碼下載
      libevent 安裝
      libevent 使用
      echo 服務器:
      echo 客戶端:
      運行結果
      libevent 源碼下載
      https://libevent.org


      libevent 安裝
      $ tar -zxvf libevent-2.1.12-stable.tar.gz
      $ cd libevent-2.1.12-stable
      $ ./configure --prefix=/opt/libevent

      在配置時 ./configure 出現錯誤:

       

      configure: error: openssl is a must but can not be found. You should add the directory containing ‘openssl.pc’ to the ‘PKG_CONFIG_PATH’ environment variable, or set ‘CFLAGS’ and ‘LDFLAGS’ directly for openssl, or use ‘–disable-openssl’ to disable support for openssl encryption

      Ubuntu 里安裝 openssl 開發工具解決上述問題

      $ sudo apt install libssl-dev
      $ openssl version # 查看 openssl 版本

      繼續安裝 libevent

      $ ./configure --prefix=/opt/libevent
      $ make
      $ sudo make install

      成功安裝至指定目錄

       

      libevent 使用
      首先環境配置,引入 libevent 的頭文件和庫文件
      我使用的是 cmake,CMakeLists.txt 如下:

      cmake_minimum_required(VERSION 3.26)
      project(libevent_server)

      set(CMAKE_CXX_STANDARD 11)

      add_executable(libevent_server main.cpp)

      set(LIBEVENT_HOME "/opt/libevent")
      target_include_directories(libevent_server PRIVATE ${LIBEVENT_HOME}/include)
      target_link_directories(libevent_server PRIVATE ${LIBEVENT_HOME}/lib)
      target_link_libraries(libevent_server -levent)

      實現一個簡單的 echo 服務器,示例代碼如下:

      #include <iostream>
      #include <cstdio>
      #include <cstring>

      #include <event.h>

      #include <sys/socket.h>
      #include <arpa/inet.h>
      #include <csignal>

      void client_cb(int fd,short events,void *arg);
      void accept_cb(int fd,short events,void *arg);
      void exit_cb(int,short,void *arg);

      int main() {
      int lfd = -1;
      struct sockaddr_in addr{0};

      // 創建監聽套接字
      lfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
      if (lfd == -1) {
      perror("socket()");
      }

      addr.sin_family = AF_INET;
      addr.sin_addr.s_addr = INADDR_ANY;
      addr.sin_port = htons(10000);

      if (bind(lfd, (struct sockaddr*)(&addr), sizeof(addr)) == -1) {
      perror("bind()");
      }
      if (listen(lfd, 10) == -1) {
      perror("listen()");
      }

      struct event_base *base = event_base_new();

      // 監聽套接字
      struct event *ev_listen = event_new(base, lfd, EV_READ | EV_PERSIST, accept_cb, base);
      event_add(ev_listen, nullptr);
      // 信號監聽
      struct event *ev_signal = evsignal_new(base, SIGINT, exit_cb, base);
      event_add(ev_signal, nullptr);

      // 開啟循環
      std::cout << "listen..." << std::endl;
      event_base_dispatch(base);

      // 退出循環,釋放資源
      event_free(ev_listen);
      event_free(ev_signal);
      event_base_free(base);

      std::cout << "\ndone..." << std::endl;
      return 0;
      }

      void client_cb(int fd,short events,void *arg) {
      auto *ev = static_cast<struct event*>(arg);

      char buf[1024]{0};
      ssize_t byte_read{0};

      // 回聲
      byte_read = recv(fd, buf, sizeof(buf), 0);
      if (byte_read == 0) {
      std::cout << "client offline" << std::endl;
      event_del(ev);
      event_free(ev);
      } else if (byte_read == -1) {
      if (errno != EINTR) {
      perror("recv()");
      event_del(ev);
      event_free(ev);
      }
      } else {
      std::cout << "client " << fd << " : " << buf;
      send(fd, buf, byte_read, 0);
      std::memset(buf, 0, byte_read);
      }
      }

      void accept_cb(int fd,short events,void *arg) {
      auto *base = static_cast<struct event_base*>(arg);
      int conn = -1;

      // 接收客戶端連接請求
      conn = accept(fd, nullptr, nullptr);
      if (conn == -1) {
      perror("accept()");
      }
      std::cout << "new client" << std::endl;

      // 添加客戶端監聽
      struct event *ev_client = event_new(base, conn, EV_READ | EV_PERSIST, client_cb, nullptr);
      event_assign(ev_client, base, conn, EV_READ | EV_PERSIST, client_cb, ev_client);
      event_add(ev_client, nullptr);
      }

      void exit_cb(int,short,void *arg) {
      auto *base = static_cast<struct event_base*>(arg);

      // 退出 event_base_dispatch()
      event_base_loopbreak(base);
      }
      使用 nc 命令向服務器發送字符串,運行結果如下:

       

      學過 IO 多路復用的話上述代碼閱讀起來應該不困難

      下面的 echo 服務器和客戶端使用了更多的 libevent API 進行實現

      echo 服務器:
      #include <iostream>
      #include <cstdio>
      #include <cstring>

      #include <event.h>
      #include <event2/listener.h>
      #include <event2/util.h>
      #include <event2/event.h>

      #include <sys/socket.h>
      #include <arpa/inet.h>
      #include <csignal>

      static void exit_cb(int,short,void *arg);

      static void conn_read_cb(struct bufferevent *bev, void *user_data);
      static void conn_write_cb(struct bufferevent *bev, void *user_data);
      static void conn_event_cb(struct bufferevent *bev, short events, void *user_data);
      static void listener_cb(struct evconnlistener *listener, int cfd, struct sockaddr *sa, int socklen, void *user_data);
      static void listener_error_cb(struct evconnlistener *listener, void *user_data);

      int main() {
      struct event_base *base;
      struct evconnlistener *listener;
      struct event *ev_signal;

      struct sockaddr_in addr{0};
      addr.sin_family = AF_INET;
      addr.sin_addr.s_addr = INADDR_ANY;
      addr.sin_port = htons(10000);

      base = event_base_new();
      if (!base) {
      std::puts("Couldn't open event base");
      return 1;
      }

      // 連接監聽
      listener = evconnlistener_new_bind(
      base,
      listener_cb, nullptr,
      LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE,
      -1,
      (struct sockaddr*)&addr,sizeof(addr));
      if (!listener) {
      perror("Couldn't create listener");
      return 1;
      }
      evconnlistener_set_error_cb(listener, listener_error_cb);

      // 信號監聽 ctrl c
      ev_signal = evsignal_new(base, SIGINT, exit_cb, base);
      event_add(ev_signal, nullptr);

      // 開啟循環
      std::cout << "listen..." << std::endl;
      //event_base_dispatch(base);
      event_base_loop(base, 0x0);

      // 退出循環,釋放資源
      evconnlistener_free(listener);
      event_free(ev_signal);
      event_base_free(base);

      std::cout << "\ndone..." << std::endl;
      return 0;
      }

      void exit_cb(int,short,void *arg) {
      auto *base = static_cast<struct event_base*>(arg);

      // 退出 event_base_dispatch()
      event_base_loopbreak(base);
      }

      void listener_cb(struct evconnlistener *listener, int cfd, struct sockaddr *sa, int socklen, void *user_data) {
      struct event_base *base = evconnlistener_get_base(listener);

      std::cout << "new client" << std::endl;
      struct bufferevent *bev = bufferevent_socket_new(base,
      cfd, BEV_OPT_CLOSE_ON_FREE);
      if (!bev) {
      std::fprintf(stderr, "Error constructing bufferevent!");
      event_base_loopbreak(base);
      return;
      }
      bufferevent_setcb(bev, conn_read_cb, conn_write_cb, conn_event_cb, nullptr);
      // 默認情況下,新創建的 bufferevent 的寫入是啟用的,但是讀取沒有啟用
      // 啟用讀
      bufferevent_enable(bev, EV_READ);
      // 關閉寫
      //bufferevent_disable(bev, EV_WRITE);
      //bufferevent_enable(bev, EV_WRITE);// 添加這行后面會直接觸發一次 conn_write_cb
      }

      void listener_error_cb(struct evconnlistener *listener, void *user_data)
      {
      struct event_base *base = evconnlistener_get_base(listener);
      int err = EVUTIL_SOCKET_ERROR();
      fprintf(stderr, "Got an error %d (%s) on the listener. "
      "Shutting down.\n", err, evutil_socket_error_to_string(err));
      event_base_loopexit(base, nullptr);
      }

      void conn_read_cb(struct bufferevent *bev, void *user_data) {
      struct evbuffer *input = bufferevent_get_input(bev);
      struct evbuffer *output = bufferevent_get_output(bev);

      char buf[1024]{0};
      int bytes_read;

      // 讀
      bytes_read = evbuffer_remove(input, buf, sizeof(buf));
      std::cout << "-------------------" << std::endl;
      std::cout << "conn_read_cb " << bufferevent_getfd(bev) << std::endl;
      std::cout << "client : " << buf;
      // 寫
      evbuffer_add(output, buf, bytes_read);
      }

      void conn_write_cb(struct bufferevent *bev, void *user_data) {

      std::cout << "conn_write_cb " << bufferevent_getfd(bev) << std::endl;
      std::cout << "-------------------" << std::endl;
      }

      void conn_event_cb(struct bufferevent *bev, short events, void *user_data) {
      if (events & BEV_EVENT_EOF) {
      std::printf("Client fd %d connection closed.\n", bufferevent_getfd(bev));
      } else if (events & BEV_EVENT_ERROR) {
      std::printf("Got an error on the connection fd %d: %s\n",
      bufferevent_getfd(bev), strerror(errno));
      }
      /* None of the other events can happen here, since we haven't enabled timeouts */
      bufferevent_free(bev);
      }


      echo 客戶端:

      #include <iostream>
      #include <cstdio>
      #include <cstring>

      #include <event2/event.h>
      #include <event2/bufferevent.h>
      #include <event2/buffer.h>

      #include <unistd.h>
      #include <sys/socket.h>
      #include <arpa/inet.h>


      static void stdin_cb(int fd,short events,void *arg);
      static void conn_read_cb(struct bufferevent *bev, void *user_data);
      static void conn_write_cb(struct bufferevent *bev, void *user_data);
      static void conn_event_cb(struct bufferevent *bev, short events, void *user_data);

      struct client_info {
      struct event_base *base;
      struct bufferevent *bev;
      };

      int main() {

      struct event_base *base = event_base_new();

      struct sockaddr_in addr{0};
      addr.sin_family = AF_INET;
      addr.sin_port = htons(10000);
      inet_aton("127.0.0.1", &addr.sin_addr);

      struct bufferevent *bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
      // 連接服務器
      bufferevent_socket_connect(bev, (struct sockaddr*)(&addr), sizeof(addr));
      bufferevent_setcb(bev, conn_read_cb, conn_write_cb, conn_event_cb, nullptr);
      bufferevent_enable(bev, EV_READ);

      struct client_info *info = new client_info;
      info->base = base;
      info->bev = bev;
      struct event *ev_stdin = event_new(base, STDIN_FILENO, EV_READ | EV_PERSIST, stdin_cb, info);
      event_add(ev_stdin, nullptr);

      std::cout << "client loop..." << std::endl;
      event_base_dispatch(base);

      event_free(ev_stdin);
      bufferevent_free(bev);
      event_base_free(base);

      std::cout << "client over..." << std::endl;
      return 0;
      }

      void stdin_cb(int fd, short events, void *arg) {
      char buf[1024]{0};
      struct client_info *info = static_cast<client_info *>(arg);
      struct evbuffer *output = bufferevent_get_output(info->bev);

      fgets(buf, sizeof(buf), stdin);
      if (std::strcmp(buf, "exit\n") == 0) {
      event_base_loopbreak(info->base);
      return;
      }

      bufferevent_write(info->bev, buf, strlen(buf));
      std::cout << "-------------------" << std::endl;
      std::cout << "stdin_cb output buffer len " << evbuffer_get_length(output) << std::endl;
      }

      void conn_read_cb(struct bufferevent *bev, void *user_data) {
      char buf[1024]{0};
      size_t bytes_read;

      bytes_read = bufferevent_read(bev, buf, sizeof(buf));

      std::cout << "conn_read_cb " << std::endl;
      std::cout << "receive from server : " << buf;
      std::cout << "-------------------" << std::endl;
      }

      void conn_write_cb(struct bufferevent *bev, void *user_data) {
      struct evbuffer *output = bufferevent_get_output(bev);

      std::cout << "conn_write_cb output buffer len " << evbuffer_get_length(output) << std::endl;
      // evbuffer_get_length(output) = 0,回調前已經發送給對端了
      }

      void conn_event_cb(struct bufferevent *bev, short events, void *user_data) {
      struct event_base *base = bufferevent_get_base(bev);

      // 成功連接
      if (events & BEV_EVENT_CONNECTED) {
      std::cout << "Connect to server successfully." << std::endl;
      }
      // 對端關閉
      else if (events & BEV_EVENT_EOF) {
      std::cout << "Server closed." << std::endl;
      event_base_loopexit(base, nullptr);
      }
      // 錯誤
      else if (events & BEV_EVENT_ERROR) {
      int err = EVUTIL_SOCKET_ERROR();
      fprintf(stderr, "Got an error %d (%s) on the bufferevent. "
      "Shutting down.\n", err, evutil_socket_error_to_string(err));
      event_base_loopexit(base, nullptr);

      ————————————————

      版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。

      原文鏈接:https://blog.csdn.net/qq_62381297/article/details/136151148

      posted @ 2024-08-22 09:27  水木清揚  閱讀(202)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 免费看的一级毛片| 欧美成人精品三级网站视频| 亚洲欧洲一区二区综合精品| 老熟妇乱子交视频一区| 97久久久精品综合88久久| 国产亚洲精品aaaa片app| 国产亚洲av日韩精品熟女| 中文 在线 日韩 亚洲 欧美| bt天堂新版中文在线| 亚洲欧美中文字幕日韩一区二区| 中文字幕色偷偷人妻久久| 国产久免费热视频在线观看| 漂亮人妻中文字幕丝袜| 亚洲av午夜成人片| 国产免费久久精品44| 午夜福利在线观看成人| 四虎在线成人免费观看| 999国产精品999久久久久久 | 999精品视频在线| 国产综合色在线精品| 成人午夜视频一区二区无码| 久久天堂无码av网站| 国产欧美另类久久久精品丝瓜| 国产成人女人在线观看| 国产成人精品久久一区二| 午夜一区欧美二区高清三区 | 一区二区不卡国产精品| 欧美日韩精品一区二区三区高清视频 | 国产亚洲精品VA片在线播放| 无码人妻人妻经典| 四虎精品寂寞少妇在线观看| 国产成人综合色视频精品| 精品一区二区无码免费| 日韩av综合中文字幕| 尹人香蕉久久99天天拍| 妺妺窝人体色www看美女| 国产午夜福利不卡在线观看| 亚洲国产欧美在线人成| 男人一天堂精品国产乱码| 午夜射精日本三级| 动漫av网站免费观看|