首页 > 解决方案 > 如何使用 libevent 非阻塞套接字找出连接被拒绝?

问题描述

我有一个说明问题的代码。此代码创建一个非阻塞套接字并将其连接到127.0.0.1:7676. 我libevent是用来获取socket事件的,比如连接、接收数据等。我不知道在使用libevent连接事件时如何获取连接失败的原因。当我使用阻塞套接字时,我可以从中获取原因WSAGetLastError并发现如果返回连接被拒绝WSAECONNREFUSED,但是当我使用 libevent 时我无法获得错误代码。即使没有超时标志,我什至无法检查套接字是否真的连接。我只能通过直接使用检查套接字状态来做到这一点getsockopt,但连接失败的原因 - 不。

void ConnectionEventCallback(evutil_socket_t s, short events, void* arg) {
  if (events & EV_TIMEOUT) {
    printf("Timeout.\n");
  } else {
    // Prints error 0.
    printf("Connection event. Error: %d.\n", GetSocketsError());
    char buf[1024];
    int len = recv(s, buf, 1024, 0);
    // Prints error 10057 (WSAENOTCONN, socket is not connected).
    printf("Recv result: %d. Last error: %d\n", len, GetSocketsError());
  }
}

int main() {
  auto remote_system_address = SystemAddressIpv4::FromTextAddress("127.0.0.1:7676");

  StartupPlatformSockets();

  SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (s == INVALID_SOCKET) {
    printf("Unable to create socket.\n");
    return 0;
  }

  const sockaddr* addr = remote_system_address->GetSocketAddress();
  const size_t len = remote_system_address->GetSocketAddressLength();

  evutil_make_socket_nonblocking(s);

  event_base* base = event_base_new();
  event* connection_event = event_new(base, s, EV_TIMEOUT | EV_WRITE, ConnectionEventCallback, nullptr);
  timeval tv;
  tv.tv_sec = 10;
  tv.tv_usec = 0;
  event_add(connection_event, &tv);

  if (connect(s, addr, len) == SOCKET_ERROR) {
    const int last_error = GetSocketsError();
    if (last_error != WSAEWOULDBLOCK) {
      printf("Unable to connect socket. Error: %d\n", last_error);
      getchar();
      return 0;
    }
  }

  event_base_loop(base, EVLOOP_NO_EXIT_ON_EMPTY);

  closesocket(s);

  getchar();
}

希望得到您的帮助!提前致谢!

标签: c++socketseventslibevent

解决方案


推荐阅读