我用 C 语言编写的 FTP 程序仅在服务器地址为 IP 地址时才有效。但是,当服务器地址是完全限定域名 (FQDN) 时,连接会失败。当 ftp_host 为 FQDN 时,ftp 连接无法打开。请帮忙。
问问题
718 次
1 回答
3
我强烈建议使用该getaddrinfo()
函数,因为gethostbyname() 已过时。这还有一个优点,即现在或以后都可以轻松转换为 IPv6。
我假设您只关心 IPv4 地址,所以这里有一个函数示例,它将以主机名作为其参数并struct sockaddr_in
为您填写 a:
int get_ftp_addr(const char *hostname, struct sockaddr_in *addr)
{
char host_buffer[256];
struct addrinfo hints;
struct addrinfo *result;
struct sockaddr_in *res_addr;
int error = -1;
char *colon;
snprintf(host_buffer, sizeof(host_buffer), "%s", hostname);
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
colon = strchr(host_buffer, ':');
if (colon) {
*colon = '\0';
error = getaddrinfo(host_buffer, colon + 1, &hints, &result);
} else {
error = getaddrinfo(host_buffer, "ftp", &hints, &result);
}
if (error != 0 || !result) {
return error;
}
res_addr = (struct sockaddr_in*)(result->ai_addr);
memcpy(addr, res_addr, sizeof(struct sockaddr_in));
freeaddrinfo(result);
return 0;
}
请注意,我只获取字符串的副本以避免修改调用者中的版本 - 如果您不想保留该部分,则不必保留,但我个人认为它使界面更清晰。
此函数将同时接受点分四边形表示法的 IP 地址和完全限定的主机名,因为getaddrinfo()
两者都接受。如果一个端口用冒号指定,它将被使用,否则将使用默认的 FTP 端口。
返回值为零表示成功。可以传递正返回gai_strerror()
以获取字符串错误代码,或者您可以查看getaddrinfo() 手册页以获取可能的错误代码。返回-1
表示来自结果结构的成功结果,getaddrinfo()
但没有结果结构 - 我认为这不会发生,但我不喜欢留下任何可能的返回代码未处理。
这里有几个警告,其中两个最重要的是:
- 这段代码只支持 IPv4,尽管
getaddrinfo()
它也很容易支持 IPv6。如果您想同时支持两者AF_INET
,则将提示结构中的 更改为AF_UNSPEC
,您将获得所有地址族。不过,您需要遍历地址,并仅过滤掉 IPv4 和 IPv6 的地址(请参阅我的下一点)。 - DNS 查找可能会查找多个 IP 地址——这在 Google 等大型站点中很常见,因为它们使用此功能来实现跨主机的负载平衡以及冗余。理想情况下,您的代码应该遍历所有返回的地址,并尝试连接到每个地址,直到一个有效。对于 FTP 客户端来说,这可能有点矫枉过正,但我认为意识到这一点很重要。
如果您想支持 IPv6,或支持多 A 记录(即从 DNS 查询返回的多个地址),那么您需要遵循结构ai_next
中的指针struct addrinfo
- 如下所示:
struct addrinfo *res;
/* Assume result is initialised as above via getaddrinfo() */
for (res = result; res != NULL; res = res->ai_next) {
...
}
于 2013-01-08T15:25:24.197 回答