私が書いた次の c 関数は、IPv4 接続を受け入れるが IPv6 接続を受け入れないファイル記述子を返します。誰かが何が悪かったのかを理解するのを手伝ってもらえますか? getaddrinfo() を正しく使用しなかったと思われます。
接続をリッスンするファイル記述子を開きます。
/*
* open_listenfd - open and return a listening socket on port
* Returns -1 and sets errno on Unix error.
*/
int open_listenfd(int port)
{
const char* hostname=0;
// Converts port to string
char* pName = malloc(numPlaces(port) + 1);
sprintf(pName, "%d", port);
const char* portname= pName;
struct addrinfo hints;
memset(&hints,0,sizeof(hints));
hints.ai_family=AF_UNSPEC;
hints.ai_socktype=SOCK_STREAM;
hints.ai_protocol= 0;
hints.ai_flags=AI_PASSIVE|AI_ADDRCONFIG;
struct addrinfo* res=0;
int err=getaddrinfo(hostname,portname,&hints,&res);
free(pName);
if (err!=0) {
return -1;
}
int listenfd, optval=1;
struct sockaddr_in serveraddr;
/* Create a socket descriptor */
if ((listenfd = socket(res->ai_family,res->ai_socktype, res->ai_protocol)) < 0)
return -1;
/* Eliminates "Address already in use" error from bind. */
if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR,
(const void *)&optval , sizeof(int)) < 0)
return -1;
/* Listenfd will be an endpoint for all requests to port
on any IP address for this host */
bzero((char *) &serveraddr, sizeof(serveraddr));
serveraddr.sin_family = /*AF_INET;*/ AF_UNSPEC;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons((unsigned short)port);
if (bind(listenfd, res->ai_addr, res->ai_addrlen/*(SA *)&serveraddr, sizeof(serveraddr)*/) < 0)
return -1;
freeaddrinfo(res);
/* Make it a listening socket ready to accept connection requests */
if (listen(listenfd, 1024) < 0)
return -1;
return listenfd;
}