Проблема заключается в следующем: написал общую ф-ию initNetAddressFromEndpoint
которая по IP адресу (IPv4, IPv6, доменное имя) и порту отдает нам структуру sockaddr_storage
. В дальнейшем эта структура передается параметром методу connect
(кастуется перед этим к sockaddr
).
Передаю данной ф-ии доменное имя машины на которой dual tcp/ip стек - т.о. можем подключится к ней как по IPv4, так и по IPv6 (сервер слушает оба unspec адреса: 0.0.0.0
и ::
). Подключение по IPv4 проходит успешно, по IPv6 - безуспешно. Может что-нибудь делаю не так?
P.S. Что-то делаю не так - скорее стоит интерпретировать как "укажите на явные ошибки, если таковые имеются". Я понимаю, что данного кода недостаточно для того, чтобы сложилась полная картина о работе софта.
Исходный код:
#if defined( _WIN32 ) && ( NTDDI_VERSION >= NTDDI_VISTA )
typedef sockaddr_in *psockaddr_in4, *psockaddr_out4;
typedef sockaddr_in6 *psockaddr_in6, *psockaddr_out6;
#define from_storage( SOSKADDRSTORAGE ) \
const_cast<sockaddr_storage*>( SOSKADDRSTORAGE )
#else
typedef sockaddr_in const *psockaddr_in4;
typedef sockaddr_in *psockaddr_out4;
typedef sockaddr_in6 const *psockaddr_in6;
typedef sockaddr_in6 *psockaddr_out6;
#define from_storage( SOSKADDRSTORAGE ) \
SOSKADDRSTORAGE
#endif
void CNetUtils::initNetAddressFromEndpoint( int inFamily
, sockaddr_storage *outAddrPtr
, CStringUtf8 const& inAddrStr
, unsigned inPort )
{
memset( outAddrPtr, 0, sizeof( sockaddr_storage ) );
struct addrinfo hints;
memset( &hints, 0, sizeof( hints ) );
hints.ai_flags = AI_NUMERICSERV;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if( inFamily == AF_INET6 )
{
psockaddr_out6 addr6 = reinterpret_cast<psockaddr_out6>( outAddrPtr );
addr6->sin6_family = AF_INET6;
addr6->sin6_port = htons( static_cast<unsigned short>( inPort ) );
if( inAddrStr == UNSPEC_IPV6_ADDRESS )
{
addr6->sin6_addr = in6addr_any;
return;
}
}
else
{
psockaddr_out4 addr4 = reinterpret_cast<psockaddr_out4>( outAddrPtr );
addr4->sin_family = AF_INET;
addr4->sin_port = htons( static_cast<unsigned short>( inPort ) );
if( inAddrStr == UNSPEC_IPV4_ADDRESS )
{
#ifdef _WIN32
addr4->sin_addr = in4addr_any;
#else
addr4->sin_addr.s_addr = INADDR_ANY;
#endif
return;
}
}
sockaddr_storage saddr;
int rc = 0;
if( inFamily == AF_INET6 )
rc = ::inet_pton( inFamily, inAddrStr.c_str(), &reinterpret_cast<psockaddr_out6>(&saddr)->sin6_addr );
else
rc = ::inet_pton( inFamily, inAddrStr.c_str(), &reinterpret_cast<psockaddr_out4>(&saddr)->sin_addr );
if( rc )
{
hints.ai_family = inFamily;
hints.ai_flags |= AI_NUMERICHOST;
}
InetAddressFormat iaf_dummy = iafUnknown;
SockAddresses sockAddrs;
getAvailableSockAddresses( sockAddrs, iaf_dummy, inAddrStr, inPort );
if( sockAddrs.empty() )
{
#ifdef _WIN32
ENetStatusException e( "CSimpleSocket: getaddrinfo failed", getSocketErrorCode() );
#else
const char *err_str = gai_strerror( rc );
ENetException e( err_str );
#endif
throw e;
}
SockAddresses::const_iterator saIt =
std::find_if( sockAddrs.cbegin(), sockAddrs.cend(), [=]( SockAddrInfo const& sa ) -> bool
{ return sa.p_family == inFamily; }
);
// this shouldn't happen
if( saIt == sockAddrs.cend() )
{
CStringBuilder buf;
buf << "Error in CNetUtils::initNetAddressFromEndpoint: \n"
<< "attempt to init netaddress for unreachable inet family [ "
<< "inetFamilyCode=" << inFamily << " ] ";
throw ENetException( buf.text() );
}
SockAddrInfo const& sa = *saIt;
if( inFamily == AF_INET6 )
{
memcpy( &reinterpret_cast<psockaddr_out6>( outAddrPtr )->sin6_addr
, &sa.p_addr
, sa.p_addr_len );
}
else
{
memcpy( &reinterpret_cast<psockaddr_out4>( outAddrPtr )->sin_addr
, &sa.p_addr
, sa.p_addr_len );
}
if( inFamily == AF_INET6 )
{
psockaddr_out6 addr6 = reinterpret_cast<psockaddr_out6>( outAddrPtr );
addr6->sin6_family = AF_INET6;
addr6->sin6_port = htons( static_cast<unsigned short>( inPort ) );
}
else
{
psockaddr_out4 addr4 = reinterpret_cast<psockaddr_out4>( outAddrPtr );
addr4->sin_family = AF_INET;
addr4->sin_port = htons( static_cast<unsigned short>( inPort ) );
}
}
getAvailableSockAddresses - по IP/порту отдает нам все возможные sockaddr'ы
void CNetUtils::getAvailableSockAddresses( SockAddresses& outAddresses
, InetAddressFormat& outUnspecAddr
, CStringUtf8 const& inAddrStr
, unsigned inPort )
{
if( inAddrStr == UNSPEC_IPV4_ADDRESS )
{
outUnspecAddr = iafIPv4;
return;
}
if( inAddrStr == UNSPEC_IPV6_ADDRESS )
{
outUnspecAddr = iafIPv6;
return;
}
struct addrinfo hints, *resaddr = 0;
memset( &hints, 0, sizeof( hints ) );
hints.ai_flags = AI_NUMERICSERV;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
int rc = getaddrinfo( inAddrStr.c_str(), CStringUtf8::fromInt32( inPort ).c_str(), &hints, &resaddr );
if( rc == 0 )
{
struct addrinfo *ai = resaddr;
while( ai != 0 )
{
SockAddrInfo sa;
sa.p_family = ai->ai_family;
sa.p_sock_type = ai->ai_socktype;
sa.p_addr_len = ai->ai_addrlen;
memcpy( &sa.p_addr, ai->ai_addr, sizeof( struct sockaddr ) );
outAddresses.push_back( sa );
ai = ai->ai_next;
}
}
if( resaddr )
freeaddrinfo( resaddr );
}
Ответ найден: вместо структуры sockaddr
следует использовать универсальную структуру sockaddr_storage
, размер которой позволяет хранит всю информацию как об IPv4
-адресе, так и об IPv6
.
Т.о.:
// typeof(sa->p_addr) = sockaddr
memcpy( &sa.p_addr, ai->ai_addr, sizeof( struct sockaddr ) );
следует заменить на:
// typeof(sa->p_addr) = sockaddr_storage
memcpy( &sa.p_addr, ai->ai_addr, ai->addrlen );
Есть код, который нужно переделать, но пока не силен в jsСейчас код вызывается inline через onclick, а мне нужно, чтобы он вызывался непосредственно...
Почему мой сайт не отображается справа при поиске по слову Fashion Flash?
Ребята помогите мне плиз, хочу чтобы мой output был robin-singh-from-usaПока, что мой output это массив ["robin", "singh", "from", "usa
Мне необходимо передать несколько фигур разом в виде json на клиент и там отрисовать их при помощи библиотеки babylonJsТам предлагают только вариант...