我正在创建套接字类,但我想使我的连接功能是动态的,可以连接到地址(ipv4或ipv6),使用交换机进行IPv测试并连接到支持的IPv,只是想问一下我是否是对的,或者有没有一个简单的方法使它成为ipv4或ipv6?
bool Connect(short port,std::string addr,bool vlisten,HWND WindowHandle,WSADATA& wsaData,bool async)
{
if(!hSocket);
{
this->port = port;
this->addr =addr;
this->vlisten = vlisten;
this->WindowHandle = WindowHandle;
this->wsaData =wsaData;
this->init = true;
// Provide big enough buffer, ipv6 should be the biggest
char ipstr[INET6_ADDRSTRLEN];
char ipstr2[INET6_ADDRSTRLEN];
struct sockaddr_in* sockaddr_ipv4;
struct sockaddr_in6* sockaddr_ipv6;
//struct sockaddr_in6* sockaddr_ipv6;
if(WSAStartup(MAKEWORD(2,2),&wsaData) !=0)
{
throw runtime_error("Error WSAStartup:" + WSAGetLastError());
}
if((this->hSocket = ::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))== INVALID_SOCKET)
{
Close();
throw runtime_error("Error init sockect:" + WSAGetLastError());
}
if(addr != "INADDR_ANY")
{
struct addrinfo *result = nullptr;
getaddrinfo(addr.c_str(), nullptr, nullptr, &result);
struct addrinfo *it;
for (it = result; it != nullptr; it = it->ai_next)
{
//sockaddr_ipv4 = reinterpret_cast<sockaddr_in*>(it->ai_addr);
//addr = inet_ntoa(sockaddr_ipv4->sin_addr);
//if (addr != "0.0.0.0") break;
switch (it->ai_family)
{
case AF_UNSPEC:
cout<<"Unspecified\n"<<endl;
break;
case AF_INET:
cout<<"AF_INET (IPv4)\n"<<endl;
sockaddr_ipv4 = reinterpret_cast<sockaddr_in*>(it->ai_addr);
//printf("\tIPv4 address %s\n",
addr = inet_ntoa(sockaddr_ipv4->sin_addr);
/*if (addr != "0.0.0.0") break;*/
break;
case AF_INET6:
cout<<"AF_INET (IPv6)\n"<<endl;
sockaddr_ipv6 = reinterpret_cast<sockaddr_in6*>(it->ai_addr);
addr = inet_ntop(it->ai_family,sockaddr_ipv6,(PSTR)ipstr,sizeof(ipstr));
break;
case AF_NETBIOS:
cout<<"AF_NETBIOS (NetBIOS)\n"<<endl;
break;
default:
printf("Other %ld\n", it->ai_family);
break;
}
}
freeaddrinfo(result);
}
}
SOCKADDR_IN sockAddrIn;
memset(&sockAddrIn,0,sizeof(sockAddrIn));
sockAddrIn.sin_port = htons(port);
sockAddrIn.sin_family = AF_INET;
sockAddrIn.sin_addr.s_addr = (addr == "INADDR_ANY" ? htonl(INADDR_ANY) : inet_addr(addr.c_str()));
if(vlisten && (bind(hSocket,reinterpret_cast<SOCKADDR*>(&sockAddrIn),sizeof(sockAddrIn))== SOCKET_ERROR))
{
Close();
throw runtime_error("Error vlisten & bind: " + WSAGetLastError());
}
if(async && WindowHandle)
{
if(WSAAsyncSelect(hSocket,WindowHandle,WM_SOCKET,FD_READ|FD_WRITE|FD_CONNECT|FD_CLOSE|FD_ACCEPT) !=0)
{
Close();
throw runtime_error("Error async & WindowHandle: " + WSAGetLastError());
}
}
if(vlisten && (listen(hSocket,SOMAXCONN)== SOCKET_ERROR))
{
Close();
throw runtime_error("Error async & WindowHandle: " + WSAGetLastError());
}
if(!vlisten && (connect(hSocket, reinterpret_cast<SOCKADDR*>(&sockAddrIn), sizeof(sockAddrIn)) == SOCKET_ERROR))
{
if(async && WindowHandle && (WSAGetLastError() != WSAEWOULDBLOCK))
{
Close();
throw runtime_error("Error async & WindowHandle: " + WSAGetLastError());
}
}
}
您的代码有多个问题:
getAddrInfo()
,但随后您完全丢弃了结果而不使用它们。listen()
但似乎打算建立传出连接;listen()
用于侦听传入的连接。sockaddr_in
结构时,您不使用getaddrinfo()
中的信息,而是忽略它并假定为IPv4。这部分代码应立即报废。让我们回到开头,得到一个最小的传出连接。我在这里省略了与创建连接没有直接关系的内容(例如,调用WSAAsyncSelect()
和其他属于单独方法的东西):
// Connect to a remote host, given its address and port number.
bool Connect(short port, std::string addr)
{
struct addrinfo *result, *rp;
// TODO: You passed us an integer port number. We need a C string.
// Clean up this mess.
char portstr[255];
portstr = sprintf("%d", port);
if (getaddrinfo(addr.c_str(), portstr, nullptr, &result)) {
throw runtime_error("getaddrinfo: " + WSAGetLastError());
}
// A host can have multiple addresses. Try each of them in turn until
// one succeeds. Typically this will try the IPv6 address first, if
// one exists, then the IPv4 address. The OS controls this ordering
// and you should not attempt to alter it. (RFC 6724)
for (rp = result; rp != nullptr; rp = rp->ai_next) {
this->hSocket = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
// Check socket creation failed; maybe harmless (e.g. computer
// doesn't have IPv6 connectivity). Real errors will get thrown below.
if (this->hSocket == -1)
continue;
if (connect(this->hSocket, rp->ai_addr, rp->ai_addrlen) != -1)
break; // Success
close(this->hSocket);
}
if (rp == NULL) { // No address succeeded
throw runtime_error("connect: " + WSAGetLastError());
}
freeaddrinfo(result);
// Now this->hSocket has an open socket connection. Enjoy!
}
问题内容: 是 InetAddress.getHostAddress()的IPv6兼容的JDK 1.6? 我具体在做 是否符合ipv6?它对ipv4和v6地址都有效吗? 问题答案: 我查看了InetAddress类的代码,它确实在做正确的事情。
我的connect调用的结果始终是10061:连接被拒绝。 如果我将服务器代码更改为绑定到::(或者将空主机传递给getaddrinfo()(同样的事情)),并将客户机代码更改为在getaddrinfo()调用中指定空主机,那么V4客户机可以很好地连接。 谁能解释一下为什么?我没有读到任何东西,如果我们想要双套接字行为,我们必须指定一个空主机(因此使用INADDR_ANY)。这不可能是一个要求,因
但是它太复杂了,无法从Java代码中完成,我认为这不是我应该使用的方向。 提前谢了。
问题内容: 我写了一个函数来为一个简单的博客引擎创建帖子: 当多个用户同时删除标签并创建帖子时,是否容易出现竞争状况? 具体来说,交易(以及功能)是否可以防止此类竞争情况的发生? 我正在使用PostgreSQL 9.2.3。 问题答案: 它的经常性问题 _ 或下可能并发写入负载,涉及(但不同于)(这是 或_)。 对于Postgres 9.5或更高版本 使用新的UPSERT实施,我们可以大大简化。P
代码如下 有人能帮忙吗,是不是在我可以把信息上传到表中之前就关闭连接了?
我有通过核心蓝牙框架连接BLE设备和通过外部附件框架连接经典蓝牙设备的应用程序(活动的和正在维护中的)。 启用/实施核心定位框架是否有助于更好地与BLE或经典蓝牙设备连接。