2011-07-22 52 views
2

操作系统是Ubuntu。 我正在为基本的IPv6操作进行简单的测试。 。 PC可通过轮毂与IP相机(支持IPv6)的连接 ping6测试成功IPv6:connect()总是失败,errno 22

$ ping6 -I eth1 fe80::240:8cff:fe94:451e 
PING fe80::240:8cff:fe94:451e(fe80::240:8cff:fe94:451e) from fe80::224:8cff:fe90:ad3b eth1: 56 data bytes 
64 bytes from fe80::240:8cff:fe94:451e: icmp_seq=1 ttl=64 time=3.86 ms 
64 bytes from fe80::240:8cff:fe94:451e: icmp_seq=2 ttl=64 time=0.471 ms 

的代码如下:

#include <linux/in6.h> 
#include <sys/socket.h> 
#include <stdio.h> 
#include <errno.h> 

void main() 
{ 
    int s, ret, err; 
    struct sockaddr_in6 addr; 

    s = socket(AF_INET6, SOCK_STREAM, 0); 
    addr.sin6_family = AF_INET6; 
    addr.sin6_port = htons(554); 
    addr.sin6_flowinfo = 0; 
    addr.sin6_scope_id = 0; 
    addr.sin6_addr.s6_addr[0] = 0xfe; 
    addr.sin6_addr.s6_addr[1] = 0x80; 
    addr.sin6_addr.s6_addr[2] = 0x00; 
    addr.sin6_addr.s6_addr[3] = 0x00; 
    addr.sin6_addr.s6_addr[4] = 0x00; 
    addr.sin6_addr.s6_addr[5] = 0x00; 
    addr.sin6_addr.s6_addr[6] = 0x00; 
    addr.sin6_addr.s6_addr[7] = 0x00; 
    addr.sin6_addr.s6_addr[8] = 0x02; 
    addr.sin6_addr.s6_addr[9] = 0x40; 
    addr.sin6_addr.s6_addr[10] = 0x8c; 
    addr.sin6_addr.s6_addr[11] = 0xff; 
    addr.sin6_addr.s6_addr[12] = 0xfe; 
    addr.sin6_addr.s6_addr[13] = 0x94; 
    addr.sin6_addr.s6_addr[14] = 0x45; 
    addr.sin6_addr.s6_addr[15] = 0x1e; 

    ret = connect(s, (struct sockaddr*)&addr, sizeof(addr)); 
    if (ret == -1) 
    { 
    err = errno; 
    printf("connect failure, errno = %d\n", err); 
    } 
} 

结果总是“连接失败, errno = 22“ 问题在哪里?

+0

你打算接受一个答案? – glglgl

+0

而不是打印err,打印strerror(err),使用%s作为格式。 –

回答

11

如果您打算使用链接本地地址,则必须将sin6_scope_id设置为与链接上网络设备的设备索引相匹配(这就是为什么您必须指定-I eth1到您的ping6命令)。

您可以getaddrinfo()做所有的辛勤工作给你,包括设置范围ID(注意%eth1在地址的末端)和端口:

struct addrinfo hints = { 0 }; 
struct addrinfo *res; 
int gai_err; 
int s; 

hints.ai_family = AF_INET6; 
hints.ai_socktype = SOCK_STREAM; 

gai_err = getaddrinfo("fe80::240:8cff:fe94:451e%eth1", "554", &hints, &res); 

if (gai_err) 
{ 
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(gai_err)); 
    return 1; 
} 

s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 

if (s < 0) { 
    perror("socket"); 
    return 1; 
} 

if (connect(s, res->ai_addr, res->ai_addrlen) < 0) { 
    perror("connect"); 
    return 1; 
}