简体   繁体   English

在不使用getaddrinfo()函数的情况下调用socket :: connect,socket :: bind,socket :: listen

[英]Calling socket::connect, socket::bind, socket::listen without using getaddrinfo( ) function before it

In all the example including Beej's Guide , the IP address is provided in dot notation and then it's fed to ::getaddrinfo() . 在包括Beej's Guide在内所有示例中,IP地址均以点表示法提供,然后将其提供给::getaddrinfo() This post doesn't answer my question. 这篇文章没有回答我的问题。

After which the addrinfo struct is used for socket related functions (eg connect() , bind() , listen() ). 之后,将addrinfo结构用于与套接字相关的功能(例如connect()bind()listen() )。 For example: 例如:

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

Example
The variable ai_addr is of type sockaddr which can be safely typecasted to sockaddr_storage , sockaddr_in and sockaddr_in6 . 变量ai_addr的类型为sockaddr ,可以安全地类型转换为sockaddr_storagesockaddr_insockaddr_in6

Question : 问题

If I typecast sockaddr to sockaddr_in (or sockaddr_in6 ) 如果我强制转换sockaddrsockaddr_in (或sockaddr_in6

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

and feed below info: 并提供以下信息:

  • ipv4.sin_family = AF_INET ipv4.sin_family = AF_INET
  • ipv4.sin_addr = [IP Address in net byte order] ipv4.sin_addr = [IP地址(以净字节顺序)
  • ipv4.sin_port = [Port number in net byte order] ipv4.sin_port = [端口号(以净字节顺序)]

Can I call the connect() method directly using above info? 我可以使用上述信息直接调用connect()方法吗?

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

With my program it doesn't appear to work. 对于我的程序,它似乎不起作用。 Am I missing something, or is there a better way? 我是否缺少某些东西,或者有更好的方法吗?

The motivation behind is that, if we have the information of IPAddress, Port etc. in socket readable format then why to go through the cycle of getaddrinfo() 其背后的动机是,如果我们具有套接字可读格式的IPAddress,Port等信息,那么为什么要经历getaddrinfo()的循环

Be sure you're placing your values in network order, here's a small example: 确保将值按网络顺序放置,这是一个小示例:

#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;
}

First check whether the machine is reachable & the server application is running on the machine using "netstat" utility. 首先使用“ netstat”实用程序检查计算机是否可访问以及服务器应用程序是否在计算机上运行。 Use inet_aton method to convert dotted address to network byte order. 使用inet_aton方法将点地址转换为网络字节顺序。 Finally, log the error value returned by the connect to get the exact reason of failure. 最后,记录连接返回的错误值以获取失败的确切原因。

It's worth noting that calling socket::{connect, bind, ...} is wrong: these are C API s and C doesn't have namespaces, classes and so on. 值得注意的是,调用socket::{connect, bind, ...}是错误的:这些是C API ,C没有名称空间,类等。

You should use getaddrinfo as it's much easier and safer to use. 您应该使用getaddrinfo因为它使用起来更容易,更安全。 But nothing prevents you from using struct sockaddr and all its variants. 但是没有什么可以阻止您使用struct sockaddr及其所有变体。 Indeed, getaddrinfo is a sort of wrapper as stated in man(3) getaddrinfo : 实际上,如man(3) getaddrinfo所述, getaddrinfo是一种包装器:

The getaddrinfo() function combines the functionality provided by the gethostbyname(3) and getservbyname(3) functions into a single interface, but unlike the latter functions, getaddrinfo() is reentrant and allows programs to eliminate IPv4-versus-IPv6 dependen‐ cies. getaddrinfo()函数将gethostbyname(3)和getservbyname(3)函数提供的功能组合到一个接口中,但是与后面的函数不同,getaddrinfo()是可重入的,并允许程序消除IPv4与IPv6的依赖。

An example: 一个例子:

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

}

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

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