⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 socket_ops.hpp

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 HPP
📖 第 1 页 / 共 4 页
字号:
inline int getsockopt(socket_type s, int level, int optname, void* optval,    size_t* optlen, boost::system::error_code& ec){  if (level == custom_socket_option_level && optname == always_fail_option)  {    ec = boost::asio::error::invalid_argument;    return -1;  }#if defined(__BORLANDC__)  // Mysteriously, using the getsockopt and setsockopt functions directly with  // Borland C++ results in incorrect values being set and read. The bug can be  // worked around by using function addresses resolved with GetProcAddress.  if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))  {    typedef int (WSAAPI *gso_t)(SOCKET, int, int, char*, int*);    if (gso_t gso = (gso_t)::GetProcAddress(winsock_module, "getsockopt"))    {      clear_error(ec);      int tmp_optlen = static_cast<int>(*optlen);      int result = error_wrapper(gso(s, level, optname,            reinterpret_cast<char*>(optval), &tmp_optlen), ec);      *optlen = static_cast<size_t>(tmp_optlen);      if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY          && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD))      {        // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are        // only supported on Windows Vista and later. To simplify program logic        // we will fake success of getting this option and specify that the        // value is non-zero (i.e. true). This corresponds to the behavior of        // IPv6 sockets on Windows platforms pre-Vista.        *static_cast<DWORD*>(optval) = 1;        clear_error(ec);      }      return result;    }  }  ec = boost::asio::error::fault;  return -1;#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)  clear_error(ec);  int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen,        s, level, optname, optval, optlen), ec);  if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY      && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD))  {    // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are only    // supported on Windows Vista and later. To simplify program logic we will    // fake success of getting this option and specify that the value is    // non-zero (i.e. true). This corresponds to the behavior of IPv6 sockets    // on Windows platforms pre-Vista.    *static_cast<DWORD*>(optval) = 1;    clear_error(ec);  }# if defined(UNDER_CE)  if (result == 0)    clear_error(ec);# endif  return result;#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)  clear_error(ec);  int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen,        s, level, optname, optval, optlen), ec);#if defined(__linux__)  if (result == 0 && level == SOL_SOCKET && *optlen == sizeof(int)      && (optname == SO_SNDBUF || optname == SO_RCVBUF))  {    // On Linux, setting SO_SNDBUF or SO_RCVBUF to N actually causes the kernel    // to set the buffer size to N*2. Linux puts additional stuff into the    // buffers so that only about half is actually available to the application.    // The retrieved value is divided by 2 here to make it appear as though the    // correct value has been set.    *static_cast<int*>(optval) /= 2;  }#endif // defined(__linux__)  return result;#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)}template <typename SockLenType>inline int call_getpeername(SockLenType msghdr::*,    socket_type s, socket_addr_type* addr, std::size_t* addrlen){  SockLenType tmp_addrlen = (SockLenType)*addrlen;  int result = ::getpeername(s, addr, &tmp_addrlen);  *addrlen = (std::size_t)tmp_addrlen;  return result;}inline int getpeername(socket_type s, socket_addr_type* addr,    std::size_t* addrlen, boost::system::error_code& ec){  clear_error(ec);  int result = error_wrapper(call_getpeername(        &msghdr::msg_namelen, s, addr, addrlen), ec);#if defined(BOOST_WINDOWS) && defined(UNDER_CE)  if (result == 0)    clear_error(ec);#endif  return result;}template <typename SockLenType>inline int call_getsockname(SockLenType msghdr::*,    socket_type s, socket_addr_type* addr, std::size_t* addrlen){  SockLenType tmp_addrlen = (SockLenType)*addrlen;  int result = ::getsockname(s, addr, &tmp_addrlen);  *addrlen = (std::size_t)tmp_addrlen;  return result;}inline int getsockname(socket_type s, socket_addr_type* addr,    std::size_t* addrlen, boost::system::error_code& ec){  clear_error(ec);  int result = error_wrapper(call_getsockname(        &msghdr::msg_namelen, s, addr, addrlen), ec);#if defined(BOOST_WINDOWS) && defined(UNDER_CE)  if (result == 0)    clear_error(ec);#endif  return result;}inline int ioctl(socket_type s, long cmd, ioctl_arg_type* arg,    boost::system::error_code& ec){  clear_error(ec);#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)  int result = error_wrapper(::ioctlsocket(s, cmd, arg), ec);# if defined(UNDER_CE)  if (result == 0)    clear_error(ec);# endif  return result;#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)  return error_wrapper(::ioctl(s, cmd, arg), ec);#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)}inline int select(int nfds, fd_set* readfds, fd_set* writefds,    fd_set* exceptfds, timeval* timeout, boost::system::error_code& ec){  clear_error(ec);#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)  if (!readfds && !writefds && !exceptfds && timeout)  {    DWORD milliseconds = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;    if (milliseconds == 0)      milliseconds = 1; // Force context switch.    ::Sleep(milliseconds);    ec = boost::system::error_code();    return 0;  }  // The select() call allows timeout values measured in microseconds, but the  // system clock (as wrapped by boost::posix_time::microsec_clock) typically  // has a resolution of 10 milliseconds. This can lead to a spinning select  // reactor, meaning increased CPU usage, when waiting for the earliest  // scheduled timeout if it's less than 10 milliseconds away. To avoid a tight  // spin we'll use a minimum timeout of 1 millisecond.  if (timeout && timeout->tv_sec == 0      && timeout->tv_usec > 0 && timeout->tv_usec < 1000)    timeout->tv_usec = 1000;#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)#if defined(__hpux) && defined(__HP_aCC)  timespec ts;  ts.tv_sec = timeout ? timeout->tv_sec : 0;  ts.tv_nsec = timeout ? timeout->tv_usec * 1000 : 0;  return error_wrapper(::pselect(nfds, readfds,        writefds, exceptfds, timeout ? &ts : 0, 0), ec);#else  int result = error_wrapper(::select(nfds, readfds,        writefds, exceptfds, timeout), ec);# if defined(BOOST_WINDOWS) && defined(UNDER_CE)  if (result >= 0)    clear_error(ec);# endif  return result;#endif}inline int poll_read(socket_type s, boost::system::error_code& ec){#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)  FD_SET fds;  FD_ZERO(&fds);  FD_SET(s, &fds);  clear_error(ec);  int result = error_wrapper(::select(s, &fds, 0, 0, 0), ec);# if defined(UNDER_CE)  if (result >= 0)    clear_error(ec);# endif  return result;#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)  pollfd fds;  fds.fd = s;  fds.events = POLLIN;  fds.revents = 0;  clear_error(ec);  return error_wrapper(::poll(&fds, 1, -1), ec);#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)}inline int poll_write(socket_type s, boost::system::error_code& ec){#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)  FD_SET fds;  FD_ZERO(&fds);  FD_SET(s, &fds);  clear_error(ec);  int result = error_wrapper(::select(s, 0, &fds, 0, 0), ec);# if defined(UNDER_CE)  if (result >= 0)    clear_error(ec);# endif  return result;#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)  pollfd fds;  fds.fd = s;  fds.events = POLLOUT;  fds.revents = 0;  clear_error(ec);  return error_wrapper(::poll(&fds, 1, -1), ec);#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)}inline int poll_connect(socket_type s, boost::system::error_code& ec){#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)  FD_SET write_fds;  FD_ZERO(&write_fds);  FD_SET(s, &write_fds);  FD_SET except_fds;  FD_ZERO(&except_fds);  FD_SET(s, &except_fds);  clear_error(ec);  int result = error_wrapper(::select(s, 0, &write_fds, &except_fds, 0), ec);# if defined(UNDER_CE)  if (result >= 0)    clear_error(ec);# endif  return result;#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)  pollfd fds;  fds.fd = s;  fds.events = POLLOUT;  fds.revents = 0;  clear_error(ec);  return error_wrapper(::poll(&fds, 1, -1), ec);#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)}inline const char* inet_ntop(int af, const void* src, char* dest, size_t length,    unsigned long scope_id, boost::system::error_code& ec){  clear_error(ec);#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)  using namespace std; // For memcpy.  if (af != AF_INET && af != AF_INET6)  {    ec = boost::asio::error::address_family_not_supported;    return 0;  }  union  {    socket_addr_type base;    sockaddr_storage_type storage;    sockaddr_in4_type v4;    sockaddr_in6_type v6;  } address;  DWORD address_length;  if (af == AF_INET)  {    address_length = sizeof(sockaddr_in4_type);    address.v4.sin_family = AF_INET;    address.v4.sin_port = 0;    memcpy(&address.v4.sin_addr, src, sizeof(in4_addr_type));  }  else // AF_INET6  {    address_length = sizeof(sockaddr_in6_type);    address.v6.sin6_family = AF_INET6;    address.v6.sin6_port = 0;    address.v6.sin6_flowinfo = 0;    address.v6.sin6_scope_id = scope_id;    memcpy(&address.v6.sin6_addr, src, sizeof(in6_addr_type));  }  DWORD string_length = static_cast<DWORD>(length);#if defined(BOOST_NO_ANSI_APIS)  LPWSTR string_buffer = (LPWSTR)_alloca(length * sizeof(WCHAR));  int result = error_wrapper(::WSAAddressToStringW(&address.base,        address_length, 0, string_buffer, &string_length), ec);  ::WideCharToMultiByte(CP_ACP, 0, string_buffer, -1, dest, length, 0, 0);#else  int result = error_wrapper(::WSAAddressToStringA(        &address.base, address_length, 0, dest, &string_length), ec);#endif  // Windows may set error code on success.  if (result != socket_error_retval)    clear_error(ec);  // Windows may not set an error code on failure.  else if (result == socket_error_retval && !ec)    ec = boost::asio::error::invalid_argument;  return result == socket_error_retval ? 0 : dest;#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)  const char* result = error_wrapper(::inet_ntop(af, src, dest, length), ec);  if (result == 0 && !ec)    ec = boost::asio::error::invalid_argument;  if (result != 0 && af == AF_INET6 && scope_id != 0)  {    using namespace std; // For strcat and sprintf.    char if_name[IF_NAMESIZE + 1] = "%";    const in6_addr_type* ipv6_address = static_cast<const in6_addr_type*>(src);    bool is_link_local = IN6_IS_ADDR_LINKLOCAL(ipv6_address);    if (!is_link_local || if_indextoname(scope_id, if_name + 1) == 0)      sprintf(if_name + 1, "%lu", scope_id);    strcat(dest, if_name);  }  return result;#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)}inline int inet_pton(int af, const char* src, void* dest,    unsigned long* scope_id, boost::system::error_code& ec){  clear_error(ec);#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)  using namespace std; // For memcpy and strcmp.  if (af != AF_INET && af != AF_INET6)  {    ec = boost::asio::error::address_family_not_supported;    return -1;  }  union  {    socket_addr_type base;    sockaddr_storage_type storage;    sockaddr_in4_type v4;    sockaddr_in6_type v6;  } address;  int address_length = sizeof(sockaddr_storage_type);#if defined(BOOST_NO_ANSI_APIS)  int num_wide_chars = strlen(src) + 1;  LPWSTR wide_buffer = (LPWSTR)_alloca(num_wide_chars * sizeof(WCHAR));  ::MultiByteToWideChar(CP_ACP, 0, src, -1, wide_buffer, num_wide_chars);  int result = error_wrapper(::WSAStringToAddressW(        wide_buffer, af, 0, &address.base, &address_length), ec);#else  int result = error_wrapper(::WSAStringToAddressA(        const_cast<char*>(src), af, 0, &address.base, &address_length), ec);#endif  if (af == AF_INET)  {    if (result != socket_error_retval)    {      memcpy(dest, &address.v4.sin_addr, sizeof(in4_addr_type));      clear_error(ec);    }    else if (strcmp(src, "255.255.255.255") == 0)    {      static_cast<in4_addr_type*>(dest)->s_addr = INADDR_NONE;      clear_error(ec);    }  }  else // AF_INET6  {    if (result != socket_error_retval)    {      memcpy(dest, &address.v6.sin6_addr, sizeof(in6_addr_type));      if (scope_id)        *scope_id = address.v6.sin6_scope_id;      clear_error(ec);    }  }  // Windows may not set an error code on failure.  if (result == socket_error_retval && !ec)    ec = boost::asio::error::invalid_argument;#if defined(UNDER_CE)  if (result != socket_error_retval)    clear_error(ec);#endif  return result == socket_error_retval ? -1 : 1;#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)  int result = error_wrapper(::inet_pton(af, src, dest), ec);  if (result <= 0 && !ec)    ec = boost::asio::error::invalid_argument;  if (result > 0 && af == AF_INET6 && scope_id)  {    using namespace std; // For strchr and atoi.    *scope_id = 0;    if (const char* if_name = strchr(src, '%'))    {      in6_addr_type* ipv6_address = static_cast<in6_addr_type*>(dest);      bool is_link_local = IN6_IS_ADDR_LINKLOCAL(ipv6_address);      if (is_link_local)        *scope_id = if_nametoindex(if_name + 1);      if (*scope_id == 0)        *scope_id = atoi(if_name + 1);    }  }  return result;#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)}inline int gethostname(char* name, int namelen, boost::system::error_code& ec){  clear_error(ec);  int result = error_wrapper(::gethostname(name, namelen), ec);#if defined(BOOST_WINDOWS) && defined(UNDER_CE)  if (result == 0)    clear_error(ec);#endif  return result;}#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) \  || defined(__MACH__) && defined(__APPLE__)// The following functions are only needed for emulation of getaddrinfo and// getnameinfo.inline boost::system::error_code translate_netdb_error(int error){  switch (error)  {  case 0:    return boost::system::error_code();  case HOST_NOT_FOUND:    return boost::asio::error::host_not_found;  case TRY_AGAIN:    return boost::asio::error::host_not_found_try_again;  case NO_RECOVERY:    return boost::asio::error::no_recovery;  case NO_DATA:    return boost::asio::error::no_data;  default:    BOOST_ASSERT(false);    return boost::asio::error::invalid_argument;  }}inline hostent* gethostbyaddr(const char* addr, int length, int af,    hostent* result, char* buffer, int buflength, boost::system::error_code& ec){  clear_error(ec);#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)  (void)(buffer);  (void)(buflength);  hostent* retval = error_wrapper(::gethostbyaddr(addr, length, af), ec);  if (!retval)    return 0;# if defined(UNDER_CE)  clear_error(ec);# endif  *result = *retval;  return retval;#elif defined(__sun) || defined(__QNX__)  int error = 0;  hostent* retval = error_wrapper(::gethostbyaddr_r(addr, length, af, result,        buffer, buflength, &error), ec);  if (error)    ec = translate_netdb_error(error);  return retval;#elif defined(__MACH__) && defined(__APPLE__)  (void)(buffer);  (void)(buflength);  int error = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -