C++ 当您有DNS名称时创建套接字
下面是我用来连接Windows中的套接字的代码。有时我没有IP地址,但在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;
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
标志(或其他等效函数),让它了解如何将地址格式化为字符串。