Когда я запускаю getaddrinfo()
на Windows против NetBSD / MacOS / Linux, я получаю некоторые существенные поведенческие различия. Если я использую буфер hints
с ai_socktype = 0:
- В системах Unixy результаты, по-видимому, включают все доступные типы сокетов. Т.е. если в системе есть SOCK_STREAM, SOCK_DGRAM, оба они будут возвращены. Для систем с SOCK_RAW также будет возвращено SOCK_RAW.
- При Windows будет возвращен один результат, и результат будет иметь
ai_socktype = 0
(т.е. он вернет вход, а не все совпадения) , Если это протокол "известного tcp" или "известного udp", в этом случае ai_socktype
устанавливается соответствующим образом.
Я использую этот небольшой пример, чтобы поэкспериментировать с:
#include <stdio.h>
#include <string.h>
#ifdef _WIN32
#include <Winsock2.h>
#include <ws2tcpip.h>
#include <assert.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#endif
int main(int argc, const char *argv[])
{
int n;
struct addrinfo *res0 = NULL, *res;
const char *hostname = NULL;
/* const char *service = "http"; */
/* const char *service = "tftp"; */
/* const char *service = "8080"; */
const char *service = "27000";
struct addrinfo hints;
#ifdef _WIN32
WSADATA wsaData;
int ret;
ret = WSAStartup(MAKEWORD(2, 2), &wsaData);
assert(ret == 0);
#endif
(void)memset(&hints, 0x00, sizeof(hints));
hints.ai_family = PF_UNSPEC;
n = getaddrinfo(hostname, service, &hints, &res0);
if(n < 0) {
return 1;
}
for(res = res0; res; res = res->ai_next) {
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
n = getnameinfo((struct sockaddr *)res->ai_addr, res->ai_addrlen,
hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
NI_NOFQDN|NI_NUMERICHOST|NI_NUMERICSERV);
if(n != 0) {
printf("getnameinfo() failed: %s\n", gai_strerror(n));
return 1;
}
printf("%s %s %u %u\n", hbuf, sbuf, (unsigned)res->ai_socktype,
(unsigned)res->ai_protocol);
}
freeaddrinfo(res0);
#ifdef _WIN32
ret = WSACleanup();
assert(ret == 0);
#endif
return 0;
}
При запуске на Windows с service
, установленным на "http", я получу ai_socktype
= SOCK_STREAM результаты (один для IPv6 и один для IPv4). При запуске с "tftp" я получаю ai_socktype
= SOCK_DGRAM результаты. 8080 дает ai_socktype
= 0 результатов, как и 27000.
Мне кажется, что Windows getaddrinfo()
возвращает "известные" (или общие) типы сокетов протокола в ai_socktype
, и когда используемая база данных getaddrinfo()
не может найти подходящих совпадений, она возвращает запись ai_socktype
= 0, по сути говоря, «семейство протоколов существует, но мы ничего не знаем о типах сокетов этого порта. предполагается, что он поддерживает ".
В то время как на платформах Unixy getaddrinfo()
ведет себя намного больше как запрос для поиска всех возможных совпадений, где ai_socktype
= 0 означает" вернуть все совпадения ". (Или, возможно, он должен делать то, что делает Windows, но tcp и udp определены неявно для всех портов?).
Правильно ли я понял различия в поведении? Есть ли способ заставить Windows 'getaddrinfo()
вести себя так же, как в системах Unixy? Я пролистал https://docs.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-getaddrinfo (извините будущих читателей, я знаю, что Microsoft нравится перемещать их документацию, ломая ссылки с течением времени), но не увидел ничего, что могло бы сделать это "соответствующим всем records ".
Кроме того, из какой базы данных Windows получены совпадения ее типа socktype? Какое-то время я волновался, что эти совпадения проводятся и в системах Unixy, просто я был слишком смущен, чтобы заметить это раньше. Вот почему у меня в этом примере service / port 27000 - этот порт не указан в моих / etc / services моего Ma c, но getaddrinfo()
по-прежнему возвращает SOCK_STREAM и SOCK_DGRAM для этого порта.
Редактировать:
Возможные значения параметра pServiceName, если номер порта не указан, перечислены в следующем файле:
% WINDIR% \ system32 \ drivers \ etc \ услуги