Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 当您有DNS名称时创建套接字_C++_Sockets_Visual C++ - Fatal编程技术网

C++ 当您有DNS名称时创建套接字

C++ 当您有DNS名称时创建套接字,c++,sockets,visual-c++,C++,Sockets,Visual C++,下面是我用来连接Windows中的套接字的代码。有时我没有IP地址,但在inetAddr中有DNS名称。可能我必须从主机名解析地址,或者可以使用DNSname创建套接字?当拥有DNSname时,创建套接字的最佳方法是什么 commStatus communicate( const char * tx, char * rx, const int bufSize , const char * inetAddr, const int port ) { ... SOCKET s;

下面是我用来连接Windows中的套接字的代码。有时我没有IP地址,但在
inetAddr
中有DNS名称。可能我必须从主机名解析地址,或者可以使用
DNS
name创建套接字?当拥有
DNS
name时,创建套接字的最佳方法是什么

commStatus communicate( const char * tx, char * rx, const int bufSize , const char * inetAddr, const int port )
{
...
        SOCKET s;
        struct sockaddr_in server;


        server.sin_addr.s_addr = inet_addr(inetAddr);
        server.sin_family = AF_INET;
        server.sin_port = htons( port );

        if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
        {

            FILELOGL("Could not create socket : " << WSAGetLastError(),Level::Error );

        } else
        {
            if (connect(s , (struct sockaddr *)&server , sizeof(server)) < 0)
            {
                FILELOGL("connect error", Level::Error);
                r= commStatus::COMM_NO_TRANSMIT ;
            } else
            {
            ...
            }
        }
...
}
commStatus通信(const char*tx、char*rx、const int bufSize、const char*inetAddr、const int端口)
{
...
插座;
服务器中的结构sockaddr_;
server.sin\u addr.s\u addr=inet\u addr(inetAddr);
server.sinu family=AF\u INET;
server.sin_port=htons(端口);
if((s=套接字(AF\u INET,SOCK\u STREAM,0))==无效的套接字)
{

FILELOGL(“无法创建套接字:”只有一种方法:解析主机名

下面是我的代码的一部分,我已经修改过,但还没有测试过,但它应该可以工作:

WSADATA wsdata;

const char * inetAddr

addrinfo hints, *res;

WSAStartup (MAKEWORD (2, 2), &wsdata);

memset(&hints, 0, sizeof hints);

hints.ai_family     = AF_UNSPEC;
hints.ai_socktype   = SOCK_STREAM;
hints.ai_protocol   = IPPROTO_TCP;

if (getaddrinfo("someaddress.com", NULL, &hints, &res) != 0)
    return false;

inetAddr = inet_ntoa(((sockaddr_in *) res -> ai_addr) -> sin_addr);

您需要解析DNS名称。用于此目的。请注意,DNS名称可以解析为多个IP,包括IPv4和IPv6,因此您必须先调用
getaddrinfo()
,以了解报告的IP数量以及为每个IP创建的套接字类型

例如:

commStatus communicate( const char * tx, char * rx, const int bufSize , const char * inetAddr, const int port )
{
    ...
    SOCKET s = INVALID_SOCKET;

    struct addrinfo hint = {0};
    hint.ai_flags = AI_NUMERICHOST;
    hint.ai_family = AF_UNSPEC;
    hint.ai_socktype = SOCK_STREAM;
    hint.ai_protocol = IPPROTO_TCP;

    struct addrinfo *addrs = NULL;
    int ret = getaddrinfo(inetAddr, NULL, &hint, &addrs);
    if (ret == EAI_NONAME)
    {
        hint.ai_flags = 0;
        ret = getaddrinfo(inetAddr, NULL, &hint, &addrs);
    }

    if (ret != 0)
    {
        FILELOGL("Could not resolve inetAddr: " << ret, Level::Error);
    }
    else
    {
        for (struct addrinfo *addr = addrs; addr != NULL; addr = addr->ai_next)
        {
            s = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
            if (s == INVALID_SOCKET)
            {
                FILELOGL("Could not create socket : " << WSAGetLastError(), Level::Error);
                break;
            }

            if (connect(s, addr->ai_addr, addr->ai_addrlen) == 0)
                break;

            closesocket(s);
            s = INVALID_SOCKET;

            if (addr->ai_next == NULL)
            {
                FILELOGL("connect error", Level::Error);
            }
        }

        freeaddrinfo(addrs);

        if (s != INVALID_SOCKET)
        {
            ...
        }
    }

    ...
}
commStatus通信(const char*tx、char*rx、const int bufSize、const char*inetAddr、const int端口)
{
...
插座s=无效的_插座;
结构addrinfo hint={0};
hint.ai_flags=ai_numericost;
hint.ai_family=AF_unsec;
hint.ai_socktype=SOCK_流;
hint.ai_protocol=IPPROTO_TCP;
struct addrinfo*addrs=NULL;
int-ret=getaddrinfo(inetAddr,NULL,&hint,&addrs);
如果(ret==EAI\U NONAME)
{
hint.ai_flags=0;
ret=getaddrinfo(inetAddr、NULL、提示和addrs);
}
如果(ret!=0)
{
FILELOGL(“无法解析inetAddr:”ai_next)
{
s=套接字(地址->ai_族,地址->ai_套接字类型,地址->ai_协议);
if(s==无效的_套接字)
{
FILELOGL(“无法创建套接字:“ai_addr,addr->ai_addrlen)==0)
打破
插座;
s=无效的_插座;
if(addr->ai_next==NULL)
{
FILELOGL(“连接错误”,级别::错误);
}
}
freeaddrinfo(addrs);
如果(s!=无效的\u插槽)
{
...
}
}
...
}

解决它,亲爱的丽莎。@MartinJames我该用什么解决它,亲爱的亨利?@ironsavier:你在发表评论之前读过已经提供的答案吗?@RemyLebeau我没有生气,但我很失望。如果你使用
getaddrinfo()
使用
AF_unsec
,它可以返回IPv4或IPv6地址,因此您必须延迟调用
socket()
直到您知道要创建什么类型的套接字,或者
AF_INET
或者
AF_INET6
。否则,如果您首先创建套接字,您必须设置
提示。ai_族
以匹配实际使用的套接字族。@RemyLebeau是的,这是正确的,但无论如何,在创建so之前,您必须调用
getaddrinfo
cket,因为他说,
inetAddr
有时是一个ip,有时是一个DNS名称,那么协议是IPv4还是IPv6并不重要。而且因为DNS查找可以报告多个ip,所以你必须尝试所有ip,直到其中一个成功。请参阅我的答案,以获取这样做的示例。@RemyLebeau我刚刚编写了易于使用的代码了解并且未完全开发,是的,确定DNS查找可以输出多个IP,但是您希望通过您的评论达到什么目的?我发布答案,您发布答案,他可以选择他接受的内容,此外,此代码一直适用于我。您显示的代码不完整。它不允许呼叫方指定IP地址,我需要n删除DNS主机名。并使用
inet\u ntoa()
假设
res->ai_addr
是IPv4,但它可能是IPv6,因为您在
提示.ai_族中使用
AF_unsec
而不是
AF_INET
。将IP地址转换为字符串时,必须检查地址的族字段,否则使用
getnameinfo()
使用
NI_numericost
标志(或其他等效函数),让它了解如何将地址格式化为字符串。