c - in_addr_t 变量作为连接参数

c - in_addr_t variable as paramether of connect

我有一个 in_addr_t 类型的变量,我想将 connect() 与给定的 ip 一起使用。因此,我需要一个 (struct sockaddr *) 变量作为 connect() 的参数。如何使用 in_addr_t 变量插入?

in_addr_t var; // Given variable, not actually declared here ofc

int sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in *srvraddr = malloc(sizeof(struct sockaddr_in));
memset((void *) srvraddr, 0, sizeof(struct sockaddr_in));
srvraddr->sin_family = AF_INET;
srvraddr->sin_port = htons(PORT_A); // Big - little endian arch compatibility

srvraddr->sin_addr.s_addr = var; // Somehow assign var here? <<<<<

connect(sockfd, (struct sockaddr *) srvraddr, sizeof(struct sockaddr_in));

无论我尝试做什么,总是联系 returns 我 -1。 使用 perror 我得到以下错误:Connection refused.

这是我使用 connect() 在端口 80 上连接到 "example.com" 的方法:

#include <stdio.h>
#include <netdb.h>
#include <unistd.h>

int main(void)
{
  int sockfd;

  if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
    fprintf(stderr, "socket");
    return 0;
  }

  char domain[] = "example.com";
  struct hostent *he;
  he = gethostbyname (domain);
  if (!he)
  {
    switch (h_errno)
    {
    case HOST_NOT_FOUND:
      fputs ("The host was not found.\n", stderr);
      break;
    case NO_ADDRESS:
      fputs ("The name is valid but it has no address.\n", stderr);
      break;
    case NO_RECOVERY:
      fputs ("A non-recoverable name server error occurred.\n", stderr);
      break;
    case TRY_AGAIN:
      fputs ("The name server is temporarily unavailable.", stderr);
      break;
    }
    return 1;
  }
  if (he->h_length < 4)
    return 1;

  struct sockaddr_in srvraddr;
  srvraddr.sin_len = sizeof(srvraddr);
  srvraddr.sin_family = AF_INET;
  srvraddr.sin_port = htons(80);

  srvraddr.sin_addr = * (struct in_addr *) he->h_addr_list[0];

  if (connect(sockfd, (struct sockaddr*)&srvraddr, srvraddr.sin_len) == -1) {
    fprintf(stderr,"connect() failed\n");
    return 1;
  }

  // Use conection here...

  close(sockfd);
  return 0;
}

How to insert use the in_addr_t variable instead?

您不能将 in_addr_tconnect() 一起使用,而不是 struct sockaddr_inconnect() 接受不同的地址结构类型,但不接受任意类型。 IPv4 地址的正确结构类型是您已经在使用的 struct sockaddr_in。您需要将远程主机地址的适当表示形式存储到其中。

显然,您已经有一个 in_addr_t,您断言它代表远程地址,但不确定如何使用它:

in_addr_t var; // Given variable, not actually declared here ofc

[...]

srvraddr->sin_addr.s_addr = var; // Somehow assign var here? <<<<<

然而,您所展示的正是 POSIX 期望您做的。 POSIX 要求 struct sockaddr_insin_addr 成员是一个至少具有 s_addr 类型 in_addr_t 成员的结构。假设您拥有的 in_addr_t 实际上是您要连接的机器地址的正确表示,将该值分配给地址结构的 sin_addr.s_addr 是正确的。原则上,该结构可以有更多成员,但实际上,想要互操作的实现不需要您设置任何其他成员。大多数人根本没有其他成员。

但是请注意,仅仅因为 connect() 通过指针接收地址结构并不意味着您需要使用动态分配。这样做会更惯用一些:

int sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in srvraddr = { 0 };

srvraddr.sin_family = AF_INET;
srvraddr.sin_port = htons(PORT_A);
srvraddr.sin_addr.s_addr = var;

connect(sockfd, (struct sockaddr *) &srvraddr, sizeof(srvraddr));

除其他外,这可以让您不必事后释放内存。

Whatever I try to do connect always returns me -1. Using perror I get the following error: Connection refused.

据我所知,您提供的代码没有问题。您可能首先要检查如何获取 in_addr_t 值,并验证您使用的端口号。另一方面,不要忽视问题出在远程主机的可能性:也许您尝试连接的端口没有打开(对您)。