简体   繁体   English

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

[英]Why are port numbers stored as strings?

The question is: Why can't I pass port numbers to DNS resolution functions as 16-bit unsigned ints to prevent std::string to unsigned short conversions?问题是:为什么我不能将端口号作为 16 位无符号整数传递给 DNS 解析函数,以防止std::stringunsigned short转换?

Background:背景:

I am looking at the Networking TS and the boost.asio implementation of the function tcp::ip::resolver::resolve .我正在查看Networking TS和函数tcp::ip::resolver::resolveboost.asio实现。 The function takes as input the web address and the port number of the service you want to connect to and performs DNS name resolution.该函数将您要连接的服务的网址和端口号作为输入,并执行 DNS 名称解析。 The signature of this function is这个函数的签名是

results_type resolve(string_view host, string_view service, ...);

As an example,举个例子,

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);

performs DNS lookup for www.google.com .www.google.com执行 DNS 查找。 Ultimately, in the TCP header, the port number will need to be stored as a 16-bit unsigned int.最终,在 TCP 标头中,端口号需要存储为 16 位无符号整数。 If the user wants to save on the std::string to unsigned short conversion, the user could have just written如果用户想要保存std::stringunsigned short转换,用户可能刚刚写了

unsigned short port_number{ 80 };

However, there is no signature in the Networking TS or the boost.asio library for但是,Networking TS 或 boost.asio 库中没有签名

results_type resolve(string_view host, PortType service, ...);

(where PortType will be a 16-bit unsigned int). (其中PortType将是 16 位无符号整数)。 Why is that?这是为什么?

Ports can also be referred to by names.端口也可以通过名称来引用。 If you look as /windows/system32/drivers/etc/services (I think) under Windows or /etc/services in *nix land, you'll see that port 80 can also be referred to as port http .如果您查看 Windows 下的/windows/system32/drivers/etc/services (我认为)或 *nix 领域的/etc/services ,您会看到端口80也可以称为端口http Names are preferred as they are better remembered, you don't need to worry what the underlying port is, and you can change the port number on the fly without having to rebuild your code just by editing the services file.首选名称,因为它们更容易记住,您无需担心底层端口是什么,并且您可以即时更改端口号,而无需仅通过编辑services文件来重建代码。

Which means that line can also be referred to as: std::string port_number{ "http" };这意味着该行也可以称为: std::string port_number{ "http" };

Because it is a thin wrapper around the POSIX getaddrinfo(3) , which takes a const char* service .因为它是 POSIX getaddrinfo(3)的薄包装器,它采用const char* service

Since a string has to be created to pass to getadddrinfo() anyways, there's not actually much benefit to having additional overloads that take uint16_t port numbers.由于无论如何都必须创建一个字符串才能传递给getadddrinfo() ,因此具有采用uint16_t端口号的额外重载实际上并没有太大的好处。 Using resolve(web_address, std::to_string(integer_port_number));使用resolve(web_address, std::to_string(integer_port_number)); works fine, and the overhead of string construction+formatting is dwarfed by the time it takes to do a DNS lookup.工作正常,字符串构造+格式化的开销与进行 DNS 查找所需的时间相比相形见绌。

There could absolutely be overloads that takes a uint16_t port.绝对可能存在占用uint16_t端口的重载。 It could do the string formatting to some internal buffer on the stack.它可以对堆栈上的某些内部缓冲区进行字符串格式化。 The savings would be tiny because of short string optimization, but at least the API user won't have to convert integers.由于短字符串优化,节省的费用很小,但至少 API 用户不必转换整数。

This seems like a thing to suggest to the Boost.Asio developers and Networking TS people.这似乎是对 Boost.Asio 开发人员和 Networking TS 人员的建议。 It has precedent in other networking APIs with Python's getaddrinfo taking ports as numbers or numeric strings, converting as necessary.它在其他网络 API 中有先例,Python 的getaddrinfo将端口作为数字或数字字符串,并根据需要进行转换。


And as an aside, ports are not specified by the internet protocol (layer 3 in the OSI model), but separately by UDP and TCP (on the transport layer, layer 4), and this is meant to be a generic resolver for anything on the IP stack.顺便说一句,端口不是由 Internet 协议(OSI 模型中的第 3 层)指定的,而是由 UDP 和 TCP(在传输层,第 4 层)分别指定的,这意味着它是任何IP 堆栈。 You can imagine some different transport layer where ports aren't 16 bit integers, but 32 bit integers or file names or something else entirely.您可以想象一些不同的传输层,其中端口不是 16 位整数,而是 32 位整数或文件名或完全其他的东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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