繁体   English   中英

为什么端口号存储为字符串?

[英]Why are port numbers stored as strings?

问题是:为什么我不能将端口号作为 16 位无符号整数传递给 DNS 解析函数,以防止std::stringunsigned short转换?

背景:

我正在查看Networking TS和函数tcp::ip::resolver::resolveboost.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::stringunsigned 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM