- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在编写一些跨平台网络代码,并且在 Windows 上的 getnameinfo()
中遇到了一些不一致的行为。和 Linux (WSL)。
下面的代码执行以下操作:
getaddrinfo()
获取地址。getnameinfo()
:
NI_NAMEREQD
设置和未设置。NI_NUMERICHOST
设置和未设置。.
// INCLUDES
#if defined(PLATFORM_WINDOWS)
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <cerrno>
#include <netdb.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#endif
#include <algorithm>
#include <cstring>
#include <functional>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
// DEBUG UTILS
namespace debug
{
#if defined(PLATFORM_WINDOWS)
void die()
{
__debugbreak();
}
#else
void die()
{
raise(SIGTRAP);
}
#endif
void die_if(bool condition)
{
if (condition)
die();
}
} // debug
// NET CODE
enum class error_code
{
no_error,
host_not_found,
try_again,
out_of_memory,
buffer_overflow,
unrecoverable_error,
system_error,
};
char const* get_error_string(error_code ec)
{
switch (ec)
{
case error_code::no_error: return "no_error";
case error_code::host_not_found: return "host_not_found";
case error_code::try_again: return "try_again";
case error_code::out_of_memory: return "out_of_memory";
case error_code::buffer_overflow: return "buffer_overflow";
case error_code::unrecoverable_error: return "unrecoverable_error";
case error_code::system_error: return "system_error";
}
debug::die();
return nullptr;
}
namespace ip
{
enum class address_family
{
v4, v6, unspecified,
};
enum class protocol
{
tcp, udp,
};
} // ip
class platform_context
{
public:
#if defined (PLATFORM_WINDOWS)
platform_context()
{
auto data = WSADATA();
auto const result = WSAStartup(MAKEWORD(2, 2), &data);
debug::die_if(result != 0);
debug::die_if(LOBYTE(data.wVersion) != 2 || HIBYTE(data.wVersion) != 2);
}
~platform_context()
{
auto const result = WSACleanup();
debug::die_if(result != 0);
}
#else
platform_context() { }
~platform_context() { }
#endif
platform_context(platform_context const&) = delete;
platform_context operator=(platform_context const&) = delete;
platform_context(platform_context&&) = delete;
platform_context operator=(platform_context&&) = delete;
};
using addrinfo_ptr = std::unique_ptr<addrinfo, std::function<void(addrinfo*)>>;
int get_ai_family(ip::address_family family)
{
switch (family)
{
case ip::address_family::v4: return AF_INET;
case ip::address_family::v6: return AF_INET6;
case ip::address_family::unspecified: return AF_UNSPEC;
}
debug::die();
return AF_UNSPEC;
}
int get_ai_socktype(ip::protocol protocol)
{
switch (protocol)
{
case ip::protocol::tcp: return SOCK_STREAM;
case ip::protocol::udp: return SOCK_DGRAM;
}
debug::die();
return SOCK_STREAM;
}
int get_ai_protocol(ip::protocol protocol)
{
switch (protocol)
{
case ip::protocol::tcp: return IPPROTO_TCP;
case ip::protocol::udp: return IPPROTO_UDP;
}
debug::die();
return IPPROTO_TCP;
}
ip::address_family get_ip_address_family(int ai_family)
{
switch (ai_family)
{
case AF_INET: return ip::address_family::v4;
case AF_INET6: return ip::address_family::v6;
case AF_UNSPEC: return ip::address_family::unspecified;
}
debug::die();
return ip::address_family::unspecified;
}
struct end_point
{
explicit end_point(addrinfo const& info):
address_length(0),
address{ 0 }
{
debug::die_if(info.ai_addrlen < 0);
debug::die_if(info.ai_addrlen > sizeof(sockaddr_storage));
address_length = static_cast<std::size_t>(info.ai_addrlen);
std::memcpy(&address, info.ai_addr, address_length);
}
ip::address_family get_address_family() const
{
return get_ip_address_family(address.ss_family);
}
std::size_t address_length;
sockaddr_storage address;
};
std::vector<end_point> get_end_points(addrinfo_ptr const& info)
{
if (!info)
return {};
auto result = std::vector<end_point>();
auto ptr = info.get();
while (ptr)
{
result.emplace_back(*ptr);
ptr = ptr->ai_next;
}
return result;
}
addrinfo_ptr get_address(error_code&, char const* node, char const* service, ip::address_family family, ip::protocol protocol, int flags)
{
debug::die_if(!node && !service);
auto hints = addrinfo();
std::memset(&hints, 0, sizeof(hints));
hints.ai_family = get_ai_family(family);
hints.ai_socktype = get_ai_socktype(protocol);
hints.ai_protocol = get_ai_protocol(protocol);
hints.ai_flags = flags;
auto out = (addrinfo*) nullptr;
auto const result = ::getaddrinfo(node, service, &hints, &out);
// error handling ignored for this example
// (make sure you have internet for testing remote end points)
debug::die_if(result != 0);
debug::die_if(out == nullptr);
return addrinfo_ptr(out, std::bind(::freeaddrinfo, std::placeholders::_1));
}
std::vector<end_point> get_wildcard_address(error_code& ec, ip::address_family family, ip::protocol protocol)
{
return get_end_points(get_address(ec, nullptr, "0", family, protocol, AI_PASSIVE));
}
std::vector<end_point> get_loopback_address(error_code& ec, ip::address_family family, ip::protocol protocol)
{
return get_end_points(get_address(ec, nullptr, "0", family, protocol, 0));
}
std::vector<end_point> get_address(error_code& ec, std::string const& node, std::string const& service, ip::address_family family, ip::protocol protocol)
{
return get_end_points(get_address(ec, node.c_str(), service.c_str(), family, protocol, 0));
};
enum class name_type
{
numeric,
name,
};
#if defined(PLATFORM_WINDOWS)
error_code get_getnameinfo_error(int result)
{
debug::die_if(result == 0);
auto const error = WSAGetLastError();
debug::die_if(error == WSANOTINITIALISED);
debug::die_if(error == WSAEAFNOSUPPORT);
debug::die_if(error == WSAEINVAL);
debug::die_if(error == WSAEFAULT);
switch (error)
{
case WSAHOST_NOT_FOUND: return error_code::host_not_found;
case WSATRY_AGAIN: return error_code::try_again;
case WSA_NOT_ENOUGH_MEMORY: return error_code::out_of_memory;
case WSANO_RECOVERY: return error_code::unrecoverable_error;
}
debug::die();
return error_code::no_error;
}
std::size_t get_cstr_len(char const* string, std::size_t max)
{
return strnlen_s(string, max);
}
#else
error_code get_getnameinfo_error(int result)
{
debug::die_if(result == 0);
auto const error = result;
debug::die_if(error == EAI_FAMILY);
debug::die_if(error == EAI_BADFLAGS);
switch (error)
{
case EAI_NONAME: return error_code::host_not_found;
case EAI_AGAIN: return error_code::try_again;
case EAI_MEMORY: return error_code::out_of_memory;
case EAI_OVERFLOW: return error_code::buffer_overflow;
case EAI_FAIL: return error_code::unrecoverable_error;
case EAI_SYSTEM: return error_code::system_error;
}
debug::die();
return error_code::no_error;
}
std::size_t get_cstr_len(char const* string, std::size_t max)
{
return strnlen(string, max);
}
#endif
//////////////
bool get_node_name(error_code& ec, std::string& node, name_type node_type, end_point const& end_point, bool require_name)
{
auto const numeric_flag = (node_type == name_type::numeric ? NI_NUMERICHOST : 0);
auto const require_flag = (require_name ? NI_NAMEREQD : 0);
char node_buffer[NI_MAXHOST] = { 0 };
auto const result = ::getnameinfo((sockaddr const*)&end_point.address, (socklen_t)end_point.address_length, node_buffer, NI_MAXHOST, nullptr, 0, numeric_flag | require_flag);
if (result != 0)
{
ec = get_getnameinfo_error(result);
return false;
}
node.resize(get_cstr_len(node_buffer, NI_MAXHOST));
std::copy_n(node_buffer, node.size(), node.begin());
return true;
}
//////////////
// TEST CODE
void test_get_node_name(end_point const& e, name_type node_type, bool name_required)
{
auto ec = error_code::no_error;
auto node = std::string();
auto result = get_node_name(ec, node, node_type, e, name_required);
std::cout << "\t"
<< (name_required ? "required - " : "not required - ")
<< (node_type == name_type::numeric ? "numeric - " : "");
if (result)
std::cout << "success (node name: '" << node << "')";
else
std::cout << "failed! (error: " << get_error_string(ec) << ")";
std::cout << "\n";
}
int main()
{
platform_context context;
std::cout << "wildcard address:" << std::endl;
{
auto ec = error_code::no_error;
auto end_points = get_wildcard_address(ec, ip::address_family::unspecified, ip::protocol::tcp);
debug::die_if(end_points.empty());
test_get_node_name(end_points.front(), name_type::name, true);
test_get_node_name(end_points.front(), name_type::name, false);
test_get_node_name(end_points.front(), name_type::numeric, true);
test_get_node_name(end_points.front(), name_type::numeric, false);
}
std::cout << "loopback address:" << std::endl;
{
auto ec = error_code::no_error;
auto end_points = get_loopback_address(ec, ip::address_family::unspecified, ip::protocol::tcp);
debug::die_if(end_points.empty());
test_get_node_name(end_points.front(), name_type::name, true);
test_get_node_name(end_points.front(), name_type::name, false);
test_get_node_name(end_points.front(), name_type::numeric, true);
test_get_node_name(end_points.front(), name_type::numeric, false);
}
std::cout << "remote address:" << std::endl;
{
auto ec = error_code::no_error;
auto end_points = get_address(ec, "www.google.com", "443", ip::address_family::unspecified, ip::protocol::tcp);
debug::die_if(end_points.empty());
test_get_node_name(end_points.front(), name_type::name, true);
test_get_node_name(end_points.front(), name_type::name, false);
test_get_node_name(end_points.front(), name_type::numeric, true);
test_get_node_name(end_points.front(), name_type::numeric, false);
}
}
这可以在 Windows 上用 cl main.cpp/DPLATFORM_WINDOWS/nologo/EHsc/W4/WX ws2_32.lib
和 g++ -Wall -Werror -std=c++ 编译17 -o main main.cpp
在 WSL 上。
我在我的系统上得到以下输出:
window :
wildcard address:
required - success (node name: 'ComputerName')
not required - success (node name: 'ComputerName')
required - numeric - success (node name: '::')
not required - numeric - success (node name: '::')
loopback address:
required - success (node name: 'ComputerName')
not required - success (node name: 'ComputerName')
required - numeric - success (node name: '::1')
not required - numeric - success (node name: '::1')
remote address:
required - success (node name: 'lhr25s12-in-f4.1e100.net')
not required - success (node name: 'lhr25s12-in-f4.1e100.net')
required - numeric - success (node name: '216.58.204.36')
not required - numeric - success (node name: '216.58.204.36')
WSL:
wildcard address:
required - failed! (error: host_not_found)
not required - success (node name: '0.0.0.0')
required - numeric - failed! (error: host_not_found)
not required - numeric - success (node name: '0.0.0.0')
loopback address:
required - success (node name: 'ip6-localhost')
not required - success (node name: 'ip6-localhost')
required - numeric - failed! (error: host_not_found)
not required - numeric - success (node name: '::1')
remote address:
required - success (node name: 'lhr25s12-in-x04.1e100.net')
not required - success (node name: 'lhr25s12-in-x04.1e100.net')
required - numeric - failed! (error: host_not_found)
not required - numeric - success (node name: '2a00:1450:4009:80d::2004')
所以 getnameinfo()
的行为差异是:
NI_NAMEREQD
时,WSL 上的数字地址查找失败。这些差异是否只是对规范的另类解释? Windows版本返回ComputerName作为主机名是否合理?
最佳答案
我还不确定通配符查找失败的原因,但在深入研究 glibc
之后,似乎 NI_NUMERICHOST
和 NI_NAMEREQD
只是不要一起工作:
/* Convert AF_INET or AF_INET6 socket address, host part. */
static int
gni_host_inet (struct scratch_buffer *tmpbuf,
const struct sockaddr *sa, socklen_t addrlen,
char *host, socklen_t hostlen, int flags)
{
if (!(flags & NI_NUMERICHOST))
{
int result = gni_host_inet_name
(tmpbuf, sa, addrlen, host, hostlen, flags);
if (result != EAI_NONAME)
return result;
}
if (flags & NI_NAMEREQD)
return EAI_NONAME;
else
return gni_host_inet_numeric
(tmpbuf, sa, addrlen, host, hostlen, flags);
}
关于c++ - `getnameinfo()` 在 WSL 上失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57928275/
我无法将 WebStorm 配置为在 WSL 中处理我的项目(这发生在我重新安装 Windows 操作系统和 WSL 之后)。我认为这个问题与 WSL 配置有关,但我找不到确切的问题。 我的项目中 E
我可以在 powershell 中使用以下命令将我的 ext4 分区挂载到 wsl-2 中: wsl --mount\\.\PHYSICALDRIVE4 --partition 1 但是,当我重新启动
我希望能够重新启动 WSL session 。这样做有点尴尬,因为 WSL 不使用 systemd 所以我们不能使用 reboot .在 WSL session 中,我们可以运行任何 Windows
我几乎完全使用 WSL,并且只切换到主窗口来浏览和运行 Windows 原生程序。我有一个位于 /mnt/c/myrepo 的 git 存储库.为了“安装”/mnt/c/myrepo 中的代码我需要将
如何在 WSL 2 上运行 Gitk? 我已经在 WSL 2 中安装了 Gitk。 安装 Gitk 后,我尝试运行它,但失败并显示以下错误日志: application-specific initia
如何在 WSL 2 上运行 Gitk? 我已经在 WSL 2 中安装了 Gitk。 安装 Gitk 后,我尝试运行它,但失败并显示以下错误日志: application-specific initia
我的 Windows 使用 Ubuntu 设置了 WSL。它已经工作了一段时间,直到我升级到 WSL2。 问题是:每次我启动我的电脑(或重新启动我的电脑)时,它都会失去从 Ubuntu 到 Windo
我的 Windows 安装了 Itellij IDEA 无法从 Ubuntu 访问 JDK(Ubuntu 安装在 WSL 上)。在运行应用程序时,我遇到了这个问题: 而且我无法在 Windows 运行
我正在努力弄清楚如何通过 WSL 中的 bash 命令启动新的“命令提示符”窗口。目标是启动第二个提示符,最好已经在 bash 中。 我已经尝试运行 cmd.exe 但这只会让我从 bash shel
在 Visual Studio 代码中选择 WSL 作为我的默认终端后,我无法打开终端窗口。终端窗口打开,屏幕上出现随机文本,然后终端关闭并显示一条错误消息:“终端进程以退出代码终止:42949672
我在这里和其他网站上搜索了很多相关的帖子,但没有解决我的问题。 如标题中所述,我正在努力在窗口操作系统的 linux 子系统上安装 docker 我用的是 win 10 家庭版,所以我已经安装了 Do
我正在从 WSL 运行 Android Studio。当我尝试使用模拟器时,我得到 "/dev/kvm" not found .我已经安装了 kvm 并且我已经确认在我的 BIOS 中启用了 vt-x
我正在运行 Windows 10,并且一直在 Windows Linux 子系统下使用 Ubuntu Linux 发行版。 我希望能够使用 Chrome.exe 或 google-chrome hea
我对 WSL 很陌生。我想在我的 win10 PC 上的 ubuntu shell 上运行 python 代码。此代码需要访问网络摄像头,但似乎网络摄像头未正确打开..我在网上查过,我发现1-2年前有
科技媒体 Phoronix 对 Windows 10 May 2020 中 WSL 和 WSL 2 的性能进行了测试,参与测试的发行版为 Ubuntu 20.04 on WSL/WSL2 ,以及 U
wget -q -O - https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo apt-key add - sudo sh -c 'ec
我在 PowerShell wsl pipenv run python ~/test.py 中运行以下命令并收到以下错误 /bin/bash: pipenv: command not found .如
有没有办法找出 WSL 的当前构建版本,即 Build 15042 - 我希望更新到此版本,按照步骤操作,但不确定它是否有效。 最佳答案 如果您要检查系统中安装的版本(我假设在更新到 Windows
我的防火墙(诺顿)阻止 WSL 2 使用互联网。我什至无法ping通谷歌。 当我关闭防火墙时,一切正常,当我再次打开它时,它不再起作用。 我必须在防火墙上设置哪些规则才能允许 WSL 通过?它适用于所
我目前正在寻求获得在 WSL 中运行的 MIPS 交叉编译器工具链,由 CLion 访问。 我遇到了一个关于 WSL 的奇怪问题。我已将以下内容添加到 .bashrc : STAGING_DIR="/
我是一名优秀的程序员,十分优秀!