我正试图了解套接字编程并遇到了一些意想不到的(对我而言)行为。
当我尝试将数据发送到“localhost”并将 addrinfo.ai_family 设置为 AF_INET 时,我发送的消息没有从我的客户端进程发送到我的主机进程(recvfrom() 不返回)。如果我将它设置为 AF_INET6 一切都很好。AF_UNSPEC 相同,在这种情况下,它会选择 IPv6 addrinfo(列表中的第一个)。当然,主机和客户端都使用相同的 ai_family。
我还尝试使用从beej 的网络编程指南粘贴的代码副本进行此操作,结果相同。我正在使用 DGRAM 插座。
我尝试从另一台电脑连接我得到相反的结果,IPv4 工作正常,IPv6 没有。我认为这可能是由于我使用了“6to4 网关”。我真的不知道这意味着什么。
问题与我自己的机器有关,因为代码在我测试过的另一台机器上通过 IPv4 工作。我不能说这是发送问题还是接收问题。
什么会阻止我使用 AF_INET 套接字向/从 localhost 发送或接收数据?
我在使用 MingW 编译的 windows7 64 位机器上。如果它有任何区别,我正在为具有不同参数的主机和客户端进程运行相同的程序。我一起运行了发布和调试程序(所以它不是同一个程序两次)但得到了相同的结果。
如果这被认为是一个愚蠢的问题,请提前致谢并道歉。
代码:
typedef struct addrinfo addrinfo_t;
typedef struct sockaddr_storage sockaddr_storage_t;
typedef struct sockaddr_in sockaddr_in_t;
typedef struct sockaddr_in6 sockaddr_in6_t;
void connect_to_server(const char* server_name, const char* message)
{
int status;
init_networking();
addrinfo_t hints;
addrinfo_t* res;
memset(&hints, 0, sizeof(addrinfo_t));
hints.ai_family = AF_INET; //or AF_INET6
hints.ai_socktype = SOCK_DGRAM;
if ((status = getaddrinfo(server_name, "4950", &hints, &res)) != 0)
{
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
exit(1);
}
SOCKET s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (s == -1)
{
fprintf(stderr, "could not create a socket, errno: %u\n", errno);
exit(1);
}
int bytes_sent = sendto(s, message, strlen(message), 0, res->ai_addr, res->ai_addrlen);
close(s);
printf("Sent %i bytes to port %i\n", bytes_sent, ((sockaddr_in_t*)res->ai_addr)->sin_port);
freeaddrinfo(res);
}
void setup_server()
{
int status;
init_networking();
addrinfo_t hints;
addrinfo_t* res;
memset(&hints, 0, sizeof(addrinfo_t));
hints.ai_family = AF_INET; //or AF_INET6
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE;
if ((status = getaddrinfo(NULL, "4950", &hints, &res)) != 0)
{
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
exit(1);
}
SOCKET s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (s == -1)
{
fprintf(stderr, "could not create a socket, errno: %u\n", errno);
exit(1);
}
//Bind the socket to own address (mostly the port number contained in the address)
if (bind(s, res->ai_addr, res->ai_addrlen) < 0)
{
fprintf(stderr, "failed to bind, errno: %u\n", errno);
exit(1);
}
freeaddrinfo(res);
const size_t read_buffer_size = 1024;
void* read_buffer = malloc(read_buffer_size);
sockaddr_storage_t peer_address;
int peer_address_length = sizeof(sockaddr_storage_t);
sockaddr_storage_t own_sock_addr;
int own_sock_addr_len = sizeof(sockaddr_storage_t);
getsockname(s, (struct sockaddr*)&own_sock_addr, &own_sock_addr_len);
printf("Listening on port %i\n", ((sockaddr_in_t*)&own_sock_addr)->sin_port);
int bytes_received = recvfrom(s,
read_buffer,
read_buffer_size-1,
0,
(struct sockaddr*)&peer_address,
&peer_address_length );
printf("Received %i byte message:\n%s\n", bytes_received, (char*)read_buffer);
}