私はソケットプログラミングに頭を悩ませようとしていますが、(私にとって) 予期しない動作に遭遇しました。
「localhost」にデータを送信して addrinfo.ai_family を AF_INET に設定しようとすると、送信するメッセージがクライアント プロセスからホスト プロセスに送信されません (recvfrom() が返されません)。AF_INET6 に設定すると、すべて問題ありません。AF_UNSPEC の場合も同様で、IPv6 addrinfo (リストの最初) を選択します。もちろん、ホストとクライアントの両方が同じ ai_family を使用します。
また、 beej のガイドからネットワーク プログラミングへのコード コピーを貼り付けてこれを試しましたが、同じ結果が得られました。DGRAM ソケットを使用しています。
別の PC から接続しようとしましたが、反対の結果が得られました。IPv4 は正常に機能し、IPv6 は機能しませんでした。これは、「6to4 ゲートウェイ」を使用していることが原因である可能性があります。これが何を意味するのか本当にわかりません。
テストした別のマシンでコードがIPv4を介して機能するため、問題は自分のマシンに関連しています。送信の問題か受信の問題かはわかりません。
AF_INET ソケットを使用して localhost との間でデータを送受信できない原因は何ですか?
私はMingWでコンパイルしているwindows7 64ビットマシンを使用しています。違いがある場合は、ホストプロセスとクライアントプロセスに対して同じプログラムを異なる引数で実行しています。リリース プログラムとデバッグ プログラムを一緒に実行しましたが (同じプログラムが 2 回実行されるわけではありません)、同じ結果が得られました。
これがばかげた質問と見なされる場合は、事前に感謝し、お詫び申し上げます。
コード:
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);
}