[英]Why are port numbers stored as strings?
问题是:为什么我不能将端口号作为 16 位无符号整数传递给 DNS 解析函数,以防止std::string
到unsigned short
转换?
背景:
我正在查看Networking TS和函数tcp::ip::resolver::resolve
的boost.asio实现。 该函数将您要连接的服务的网址和端口号作为输入,并执行 DNS 名称解析。 这个函数的签名是
results_type resolve(string_view host, string_view service, ...);
举个例子,
boost::asio::io_context serv{};
boost::asio::ip::tcp::resolver res{serv};
std::string web_address{ "www.google.com" };
std::string port_number{ "80" };
auto result = res.resolve(web_address, port_number);
对www.google.com执行 DNS 查找。 最终,在 TCP 标头中,端口号需要存储为 16 位无符号整数。 如果用户想要保存std::string
到unsigned short
转换,用户可能刚刚写了
unsigned short port_number{ 80 };
但是,Networking TS 或 boost.asio 库中没有签名
results_type resolve(string_view host, PortType service, ...);
(其中PortType
将是 16 位无符号整数)。 这是为什么?
端口也可以通过名称来引用。 如果您查看 Windows 下的/windows/system32/drivers/etc/services
(我认为)或 *nix 领域的/etc/services
,您会看到端口80
也可以称为端口http
。 首选名称,因为它们更容易记住,您无需担心底层端口是什么,并且您可以即时更改端口号,而无需仅通过编辑services
文件来重建代码。
这意味着该行也可以称为: std::string port_number{ "http" };
因为它是 POSIX getaddrinfo(3)
的薄包装器,它采用const char* service
。
由于无论如何都必须创建一个字符串才能传递给getadddrinfo()
,因此具有采用uint16_t
端口号的额外重载实际上并没有太大的好处。 使用resolve(web_address, std::to_string(integer_port_number));
工作正常,字符串构造+格式化的开销与进行 DNS 查找所需的时间相比相形见绌。
绝对可能存在占用uint16_t
端口的重载。 它可以对堆栈上的某些内部缓冲区进行字符串格式化。 由于短字符串优化,节省的费用很小,但至少 API 用户不必转换整数。
这似乎是对 Boost.Asio 开发人员和 Networking TS 人员的建议。 它在其他网络 API 中有先例,Python 的getaddrinfo
将端口作为数字或数字字符串,并根据需要进行转换。
顺便说一句,端口不是由 Internet 协议(OSI 模型中的第 3 层)指定的,而是由 UDP 和 TCP(在传输层,第 4 层)分别指定的,这意味着它是任何IP 堆栈。 您可以想象一些不同的传输层,其中端口不是 16 位整数,而是 32 位整数或文件名或完全其他的东西。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.