原文:http://blog.csdn.net/caspiansea/article/details/29779655
写了一个 IPv6的服务端和客户端的程序,功能就是服务端重复一下客户端的输入(根据 UNP代码改的)。
代码如下:
server6.c:
- #include <sys/socket.h>
- #include <sys/types.h>
- #include <netinet/in.h>
- #include <errno.h>
- #include <stdlib.h>
- #include <string.h>
-
- #define SERV_PORT 9877
- #define LISTENQ 1024
- extern int echo(int sockfd);
- int main(int argc, char ** argv)
- {
- int listenfd, connfd;
- struct sockaddr_in6 servaddr, cliaddr;
-
- listenfd = socket(AF_INET6, SOCK_STREAM, 0);
-
- if(listenfd == 0)
- {
- perror("socket create error");
- exit(1);
- }
-
- bzero(&servaddr, sizeof(servaddr));
- servaddr.sin6_family = AF_INET6;
- servaddr.sin6_addr = in6addr_any;
- servaddr.sin6_port = htons(SERV_PORT);
-
- if(bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1)
- {
- perror("bind error");
- exit(2);
- }
-
- if(listen(listenfd, LISTENQ) == -1)
- {
- perror("listen error");
- exit(3);
- }
-
-
- for(; ;)
- {
- socklen_t clien = sizeof(struct sockaddr);
- connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clien);
- if(connfd == -1)
- {
- perror("accept error");
- exit(4);
- }
-
- pid_t childpid = fork();
- if(childpid == -1)
- {
- perror("fork error");
- exit(5);
- }
- else if(childpid == 0)
- {
- close(listenfd);
- echo(connfd);
- exit(0);
- }
- close(connfd);
- }
- }
client6.c:
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #define SERV_PORT 9877
-
- int main(int argc, char **argv)
- {
- int sockfd;
- struct sockaddr_in6 servaddr;
-
- if(argc != 2)
- {
- printf("usage: %s server address\n", argv[0]);
- exit(0);
- }
-
-
- sockfd = socket(AF_INET6, SOCK_STREAM, 0);
-
- if(sockfd == -1)
- {
- perror("socket error");
- exit(1);
- }
-
- bzero(&servaddr, sizeof(servaddr));
- servaddr.sin6_family = AF_INET6;
- servaddr.sin6_port = htons(SERV_PORT);
-
- int n = inet_pton(AF_INET6, argv[1], &servaddr.sin6_addr);
- if(n == 0)
- {
- fprintf(stderr, "not in presentation format\n");
- exit(2);
- }
- else if(n == -1)
- {
- perror("inet_pton error");
- exit(3);
- }
-
- printf("sizeof(servaddr) = %d\n", sizeof(servaddr));
- if(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(struct sockaddr_in6)) == -1)
- {
- perror("connect error:");
- exit(4);
- }
-
- str_cli(stdin, sockfd);
- return 0;
- }
但是客户端在使用 IPv6地址连接服务器程序的时候,出现错误:
- t#./client6 fe80::5054:ff:fe12:3456
- connect error:: Invalid argument
fe80::5054:ff:fe12:3456 为 IPv6地址 (link-local).
但是加上一个其它类型的地址 (如global 的),然后, client就能连上了。
- sudo ip addr add 2001:470:1f01:f52b::2/64 dev wlan0
- or
- <pre name="code" class="plain">sudo ifconfig wlan0 inet6 add 2001:470:1f01:f52b::2/64
- wlan0 Link encap:Ethernet HWaddr ec:55:f9:bf:7c:16
- inet addr:192.168.1.102 Bcast:192.168.1.255 Mask:255.255.255.0
- inet6 addr: fe80::ee55:f9ff:febf:7c16/64 Scope:Link
- inet6 addr: 2001:470:1f01:f52b::2/64 Scope:Global
- UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
- RX packets:2445788 errors:0 dropped:0 overruns:0 frame:0
- TX packets:1667005 errors:0 dropped:0 overruns:0 carrier:0
- collisions:0 txqueuelen:1000
- RX bytes:2493540196 (2.4 GB) TX bytes:284771192 (284.7 MB)
- ./client6 2001:470:1f01:f52b::2
- sizeof(servaddr) = 28
- 1
- 1
网上有资料说
- You got a bit more to cover to get up and flying with IPv6. Like you
- should NOT be using Link Local addresses for anything in user space (they're
- primarily used in the kernel and lower level protocol stuff for things like
- neighbor discovery and router solicitation. You can use them with certain
- apps, like ping6, IF you know what you are doing. But not with apps which
- don't understand what you are doing.
References:
http://www.derkeiler.com/Mailing-Lists/securityfocus/Secure_Shell/2004-01/0013.html
http://www.tldp.org/HOWTO/Linux+IPv6-HOWTO/index.html
http://www.bieringer.de/linux/IPv6/IPv6-HOWTO/IPv6-HOWTO-6.html
https://wiki.ubuntu.com/IPv6