8

IPv4アドレスとIPv6アドレスの両方をリッスンするWebサーバーを作成しようとしています。しかし、私が最初に書いたコードは機能しませんでした。次に、IPv6構造がIPv4とIPv6の両方で機能することを発見しました。そのため、現在はIPv6構造を使用していますが、IPv4アドレスのみが機能します。この投稿では、 ipv6ソケットをリンクローカルアドレスにバインドできないのはなぜですか。追加すると言われているので、追加しましたが、IPv6telnetserver.sin6_scope_id = 5;接続はまだ受け入れられません。私は完全に困惑しているので、どんな助けでも大歓迎です。
ありがとう!

私のコードは以下の通りです:

void initialize_server(int port, int connections, char* address)
{
        struct sockaddr_in6 socket_struct;
        /*Creates the socket*/
        if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
        {
                syslog(LOG_ERR, "%s\n", strerror(errno));
                exit(EXIT_FAILURE);
        }/*Ends the socket creation*/

        /*Populates the socket address structure*/
                socket_struct.sin6_family = AF_INET6;

        if(address == NULL)
                socket_struct.sin6_addr=in6addr_any;
        else
        {
                inet_pton(AF_INET6, "fe80::216:3eff:fec3:3c22", (void *)&socket_struct.sin6_addr.s6_addr);
        }
        socket_struct.sin6_port =htons(port);
        socket_struct.sin6_scope_id = 0;
        if (bind(sock_fd, (struct sockaddr*) &socket_struct, sizeof(socket_struct)) < 0)
        {
                syslog(LOG_ERR, "%s\n", strerror(errno));
                exit(EXIT_FAILURE);
        }//Ends the binding.

        if (listen(sock_fd, connections) <0)
        {
                syslog(LOG_ERR, "%s\n", strerror(errno));
                exit(EXIT_FAILURE);
        }//Ends the listening function

}//ends the initialize server function.
4

2 に答える 2

8

「server.sin6_scope_id = 5;」と言って 任意です。私はこれとしばらく戦い、バインドしたい実際のインターフェースの実際のスコープを使用する必要があることを発見しました。目立たないが便利な小さな関数で見つけることができます。

#include <net/if.h>
server.sin6_scope_id=if_nametoindex("eth0");

もちろん、特定のアダプターにハードコーディングするのは、近視眼的な不適切なコーディングです。より完全な解決策は、それらすべてをループして、バインドしている IP アドレスを照合することです。以下は、非標準アドレスや同じ ip を持つ 2 つのアダプターなどの癖を考慮していないという点で完全ではありません。

#include <string.h> // strcmp
#include <net/if.h> // if_nametoindex()
#include <ifaddrs.h> // getifaddrs()
#include <netdb.h> // NI_ constants

// returns 0 on error
unsigned getScopeForIp(const char *ip){
    struct ifaddrs *addrs;
    char ipAddress[NI_MAXHOST];
    unsigned scope=0;
    // walk over the list of all interface addresses
    getifaddrs(&addrs);
    for(ifaddrs *addr=addrs;addr;addr=addr->ifa_next){
        if (addr->ifa_addr && addr->ifa_addr->sa_family==AF_INET6){ // only interested in ipv6 ones
            getnameinfo(addr->ifa_addr,sizeof(struct sockaddr_in6),ipAddress,sizeof(ipAddress),NULL,0,NI_NUMERICHOST);
            // result actually contains the interface name, so strip it
            for(int i=0;ipAddress[i];i++){
                if(ipAddress[i]=='%'){
                    ipAddress[i]='\0';
                    break;
                }
            }
            // if the ip matches, convert the interface name to a scope index
            if(strcmp(ipAddress,ip)==0){
                scope=if_nametoindex(addr->ifa_name);
                break;
            }
        }
    }
    freeifaddrs(addrs);
    return scope;
}
于 2014-04-17T20:19:53.973 に答える
6

ファミリ内にソケットを作成していますが、それをファミリAF_INET内のアドレスにバインドしようとしていますAF_INET6AF_INET6への通話でusingに切り替えますsocket()

于 2012-11-22T03:03:44.280 に答える