0

在包括Beej's Guide在内的所有示例中,IP 地址以点表示法提供,然后馈送到::getaddrinfo(). 这篇文章没有回答我的问题。

之后,该addrinfo结构用于与套接字相关的功能(例如connect(),、、bind()listen()。例如:

struct addrinfo hints, *res;
// ... create socket etc.
connect(sockfd, res->ai_addr, res->ai_addrlen);

示例
变量ai_addr的类型sockaddr可以安全地转换为sockaddr_storage,sockaddr_insockaddr_in6

问题

如果我将类型转换sockaddrsockaddr_in(或sockaddr_in6

sockaddr_in& ipv4 = (sockaddr_in&)(sockaddr_variable);

并提供以下信息:

  • ipv4.sin_family = AF_INET
  • ipv4.sin_addr = [网络字节顺序的IP地址]
  • ipv4.sin_port = [网络字节顺序的端口号]

connect()可以使用上述信息直接调用该方法吗?

connect(sockfd, &ipv4, sizeof(ipv4));

使用我的程序,它似乎不起作用。我错过了什么,还是有更好的方法?

背后的动机是,如果我们有套接字可读格式的 IPAddress、Port 等信息,那么为什么要经过循环getaddrinfo()

4

3 回答 3

2

确保将值按网络顺序排列,这是一个小例子:

#include<stdio.h>
#include<sys/socket.h>
#include<arpa/inet.h>

int main(int argc, char *argv[])
{
    int sock;
    struct sockaddr_in server;

    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == -1)
    {
        printf("Could not create socket\n");
    }
    printf("Socket created\n");

    server.sin_family = AF_INET;
    // 173.194.32.207 is a google address
    server.sin_addr.s_addr = 173 | 194 << 8 | 32 << 16 | 207 << 24;
    server.sin_port = 0x5000; // port 80

    if (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0)
    {
        perror("connect failed. Error");
        return 1;
    }

    printf("Connected\n");

    close(sock);
    return 0;
}
于 2014-08-09T16:41:56.380 回答
0

首先使用“netstat”实用程序检查机器是否可访问以及服务器应用程序是否正在机器上运行。使用 inet_aton 方法将点分地址转换为网络字节顺序。最后,记录连接返回的错误值,以获取失败的确切原因。

于 2014-08-09T17:20:01.537 回答
0

值得注意的是,调用socket::{connect, bind, ...}是错误的:这些是C API​​ s 而 C 没有命名空间、类等。

您应该使用getaddrinfo它,因为它使用起来更容易、更安全。但是没有什么能阻止您使用struct sockaddr它及其所有变体。实际上,getaddrinfo是一种包装器,如中所述man(3) getaddrinfo

getaddrinfo() 函数将 gethostbyname(3) 和 getservbyname(3) 函数提供的功能组合到一个接口中,但与后者不同的是,getaddrinfo() 是可重入的,允许程序消除 IPv4 与 IPv6 的依赖关系.

一个例子:

#include <sys/socket.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main()
{
   struct sockaddr_in addr = {0};
   addr.sin_family = AF_INET;
   addr.sin_port   = htons(80);

  inet_pton(addr.sin_family, "198.252.206.16", &addr.sin_addr);

  int fd = socket(addr.sin_family, SOCK_STREAM, 0);

  if (fd == -1)
       ; /* could not create socket */

  if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
        ;  /* could not connect */

   close(fd);

}
于 2014-08-09T17:39:42.003 回答