套接字编程:bind() - 无效的参数

时间:2015-06-22 16:02:18

标签: c sockets interface bind ipv6

我正在尝试将本地IPv6地址绑定到套接字。但总是得到"无效的论证"。我想将特定IP地址绑定到套接字的原因是,如果我没有绑定错误"没有到主机的路由"来了当我尝试使用下面的命令ping IPv6地址时,它不起作用。

ping6 fe80::7ed1:c3ff:fe86

我必须指出我想从哪个接口发送数据包。

ping6 -I en1 fe80::7ed1:c3ff:fe86

这很好用。所以我认为如果我将套接字绑定到接口,那么我可以成功发送数据包。 任何人都可以告诉我如何在不指定界面的情况下发送IPv6地址或如何解决绑定问题?

以下是代码。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <netdb.h>

#define LOCALADDR "fe80::7ed1:c3ff:fe86:ddae"

int main(void)
{
int sock,status;
struct addrinfo local_addr;
struct addrinfo *servinfo;
char buffer[1024];

/* create a DGRAM (UDP) socket in the INET6 (IPv6) protocol */
sock = socket(PF_INET6, SOCK_DGRAM, 0);

if (sock < 0) {
    perror("creating socket");
    exit(1);
}

/*Binding specific interface to socket*/
memset(&local_addr, 0, sizeof(local_addr));
local_addr.ai_family = AF_INET6;
local_addr.ai_socktype = SOCK_DGRAM;
local_addr.ai_flags = AI_PASSIVE;

if ((status = getaddrinfo(NULL, "3535", &local_addr, &servinfo)) != 0) {
    fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
    exit(1);
}

if (bind(sock, (struct sockaddr *) &local_addr, sizeof(local_addr)) < 0)
    error("ERROR on binding");

我也试过替换&#34; NULL&#34;在&#34; getaddrinfo&#34;成为&#34; LOCALADDR&#34;。

if ((status = getaddrinfo(LOCALADDR, "3535", &local_addr, &servinfo)) != 0) {
    fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
    exit(1);
}

我仍然遇到同样的问题。

我可以使用&#34; in6addr_any&#34;成功绑定套接字,但后来我收到错误&#34;没有到主机的路由&#34;。

2 个答案:

答案 0 :(得分:1)

这是链路本地IPv6地址,而不是可路由的IPv6地址。链路本地地址特定于链路,并且每个链路可以具有与其他链路相同的地址。例如,如果您有三个不同的接口,则可以为每个接口分配相同的链路本地地址。要使用链接本地地址,您需要指定接口,以便操作系统知道要使用的链接。所有接口都在同一网络中具有链路本地地址:fe80 :: / 10。

如果使用可路由的IPv6地址,则无需指定接口。

答案 1 :(得分:0)

您正在错误地创建套接字。 &#39;域名&#39; (第一个参数)应该是AF_INET6,而不是PF_INET6。我不确定这些是否实际上扩展到您环境中的不同值,但AF_*宏是为此目的指定的。

否则,对于接受连接的套接字,您应该获得与首次出现的方式相同的地址。特别是,getaddrinfo()的文档说

  

如果在AI_PASSIVE中指定了hints.ai_flags标志,并且node为NULL,则返回的套接字地址将适用于bind(2)套接字将accept(2)连接。返回的套接字地址将包含&#34;通配符地址&#34; (INADDR_ANY表示IPv4地址,IN6ADDR_ANY_INIT表示IPv6地址)。通配符地址由打算接受任何主机网络地址上的连接的应用程序(通常是服务器)使用。如果node不为NULL,则忽略AI_PASSIVE标志。

因此,您当然可以并且可能应该指定NULL第一个参数。

但请注意,getaddrinfo()会返回一个链接的地址列表,在某些情况下,必须选择与第一个不同的地址。我认为在这个特殊情况下,第一个应该没问题。

还要注意a&#34;没有主持人的路线&#34;来自尝试连接的客户端的消息不一定表明服务器没有正在侦听。很可能是客户端使用了错误的地址(参见@ RonMaupin的回答),或者正如它所说的那样,从客户端到服务器的网络中没有(已知的)路由。例如,由于路由器或防火墙配置,可能会出现这种情况。