TCP socket ipv6與ipv4的區別

一、TCP socket ipv6與ipv4的區別

服務器端源代碼如下:

[cpp] view plain copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <errno.h>  
  4. #include <string.h>  
  5. #include <sys/types.h>  
  6. #include <netinet/in.h>  
  7. #include <sys/socket.h>  
  8. #include <sys/wait.h>  
  9. #include <unistd.h>  
  10. #include <arpa/inet.h>  
  11. #define MAXBUF 1024  
  12. int main(int argc, char **argv)  
  13. {  
  14.     int sockfd, new_fd;  
  15.     socklen_t len;  
  16.   
  17.     /* struct sockaddr_in my_addr, their_addr; */ // IPv4  
  18.     struct sockaddr_in6 my_addr, their_addr; // IPv6  
  19.   
  20.     unsigned int myport, lisnum;  
  21.     char buf[MAXBUF + 1];  
  22.   
  23.     if (argv[1])  
  24.         myport = atoi(argv[1]);  
  25.     else  
  26.         myport = 7838;  
  27.   
  28.     if (argv[2])  
  29.         lisnum = atoi(argv[2]);  
  30.     else  
  31.         lisnum = 2;  
  32.   
  33.     /* if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { */ // IPv4  
  34.     if ((sockfd = socket(PF_INET6, SOCK_STREAM, 0)) == -1) { // IPv6  
  35.         perror("socket");  
  36.         exit(1);  
  37.     } else  
  38.         printf("socket created/n");  
  39.   
  40.     bzero(&my_addr, sizeof(my_addr));  
  41.     /* my_addr.sin_family = PF_INET; */ // IPv4  
  42.     my_addr.sin6_family = PF_INET6;    // IPv6  
  43.     /* my_addr.sin_port = htons(myport); */ // IPv4  
  44.     my_addr.sin6_port = htons(myport);   // IPv6  
  45.     if (argv[3])  
  46.         /* my_addr.sin_addr.s_addr = inet_addr(argv[3]); */ // IPv4  
  47.         inet_pton(AF_INET6, argv[3], &my_addr.sin6_addr);  // IPv6  
  48.     else  
  49.         /* my_addr.sin_addr.s_addr = INADDR_ANY; */ // IPv4  
  50.         my_addr.sin6_addr = in6addr_any;            // IPv6  
  51.   
  52.     /* if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) */ // IPv4  
  53.     if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr_in6))  // IPv6  
  54.         == -1) {  
  55.         perror("bind");  
  56.         exit(1);  
  57.     } else  
  58.         printf("binded/n");  
  59.   
  60.     if (listen(sockfd, lisnum) == -1) {  
  61.         perror("listen");  
  62.         exit(1);  
  63.     } else  
  64.         printf("begin listen/n");  
  65.   
  66.     while (1) {  
  67.         len = sizeof(struct sockaddr);  
  68.         if ((new_fd =  
  69.              accept(sockfd, (struct sockaddr *) &their_addr,  
  70.                     &len)) == -1) {  
  71.             perror("accept");  
  72.             exit(errno);  
  73.         } else  
  74.             printf("server: got connection from %s, port %d, socket %d/n",  
  75.                    /* inet_ntoa(their_addr.sin_addr), */ // IPv4  
  76.                    inet_ntop(AF_INET6, &their_addr.sin6_addr, buf, sizeof(buf)), // IPv6  
  77.                    /* ntohs(their_addr.sin_port), new_fd); */ // IPv4  
  78.                    their_addr.sin6_port, new_fd); // IPv6  
  79.   
  80.         /* 開始處理每個新連接上的數據收發 */  
  81.         bzero(buf, MAXBUF + 1);  
  82.         strcpy(buf,  
  83.                "這是在連接建立成功後向客戶端發送的第一個消息/n只能向new_fd這個用accept函數新建立的socket發消息,不能向sockfd這個監聽socket發送消息,監聽socket不能用來接收或發送消息/n");  
  84.         /* 發消息給客戶端 */  
  85.         len = send(new_fd, buf, strlen(buf), 0);  
  86.         if (len < 0) {  
  87.             printf  
  88.                 ("消息'%s'發送失敗!錯誤代碼是%d,錯誤信息是'%s'/n",  
  89.                  buf, errno, strerror(errno));  
  90.         } else  
  91.             printf("消息'%s'發送成功,共發送了%d個字節!/n",  
  92.                    buf, len);  
  93.   
  94.         bzero(buf, MAXBUF + 1);  
  95.         /* 接收客戶端的消息 */  
  96.         len = recv(new_fd, buf, MAXBUF, 0);  
  97.         if (len > 0)  
  98.             printf("接收消息成功:'%s',共%d個字節的數據/n",  
  99.                    buf, len);  
  100.         else  
  101.             printf  
  102.                 ("消息接收失敗!錯誤代碼是%d,錯誤信息是'%s'/n",  
  103.                  errno, strerror(errno));  
  104.         /* 處理每個新連接上的數據收發結束 */  
  105.     }  
  106.   
  107.     close(sockfd);  
  108.     return 0;  
  109. }  
每行程序後面的 “//IPv4” 表示這行代碼是在IPv4網絡裏用的
而“//IPv6” 表示這行代碼是在IPv6網絡裏用的,比較一下,會很容易看到差別的。
客戶端源代碼如下:

[cpp] view plain copy
  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #include <errno.h>  
  4. #include <sys/socket.h>  
  5. #include <resolv.h>  
  6. #include <stdlib.h>  
  7. #include <netinet/in.h>  
  8. #include <arpa/inet.h>  
  9. #include <unistd.h>  
  10. #define MAXBUF 1024  
  11. int main(int argc, char **argv)  
  12. {  
  13.     int sockfd, len;  
  14.     /* struct sockaddr_in dest; */ // IPv4  
  15.     struct sockaddr_in6 dest;      // IPv6  
  16.     char buffer[MAXBUF + 1];  
  17.   
  18.     if (argc != 3) {  
  19.         printf  
  20.             ("參數格式錯誤!正確用法如下:/n/t/t%s IP地址 端口/n/t比如:/t%s 127.0.0.1 80/n此程序用來從某個 IP 地址的服務器某個端口接收最多 MAXBUF 個字節的消息",  
  21.              argv[0], argv[0]);  
  22.         exit(0);  
  23.     }  
  24.     /* 創建一個 socket 用於 tcp 通信 */  
  25.     /* if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { */ // IPv4  
  26.     if ((sockfd = socket(AF_INET6, SOCK_STREAM, 0)) < 0) {      // IPv6  
  27.         perror("Socket");  
  28.         exit(errno);  
  29.     }  
  30.     printf("socket created/n");  
  31.   
  32.     /* 初始化服務器端(對方)的地址和端口信息 */  
  33.     bzero(&dest, sizeof(dest));  
  34.     /* dest.sin_family = AF_INET; */  // IPv4  
  35.     dest.sin6_family = AF_INET6;     // IPv6  
  36.     /* dest.sin_port = htons(atoi(argv[2])); */ // IPv4  
  37.     dest.sin6_port = htons(atoi(argv[2]));     // IPv6  
  38.     /* if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0) { */ // IPv4  
  39.     if ( inet_pton(AF_INET6, argv[1], &dest.sin6_addr) < 0 ) {                 // IPv6  
  40.         perror(argv[1]);  
  41.         exit(errno);  
  42.     }  
  43.     printf("address created/n");  
  44.   
  45.     /* 連接服務器 */  
  46.     if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0) {  
  47.         perror("Connect ");  
  48.         exit(errno);  
  49.     }  
  50.     printf("server connected/n");  
  51.   
  52.     /* 接收對方發過來的消息,最多接收 MAXBUF 個字節 */  
  53.     bzero(buffer, MAXBUF + 1);  
  54.     /* 接收服務器來的消息 */  
  55.     len = recv(sockfd, buffer, MAXBUF, 0);  
  56.     if (len > 0)  
  57.         printf("接收消息成功:'%s',共%d個字節的數據/n",  
  58.                buffer, len);  
  59.     else  
  60.         printf  
  61.             ("消息接收失敗!錯誤代碼是%d,錯誤信息是'%s'/n",  
  62.              errno, strerror(errno));  
  63.   
  64.     bzero(buffer, MAXBUF + 1);  
  65.     strcpy(buffer, "這是客戶端發給服務器端的消息/n");  
  66.     /* 發消息給服務器 */  
  67.     len = send(sockfd, buffer, strlen(buffer), 0);  
  68.     if (len < 0)  
  69.         printf  
  70.             ("消息'%s'發送失敗!錯誤代碼是%d,錯誤信息是'%s'/n",  
  71.              buffer, errno, strerror(errno));  
  72.     else  
  73.         printf("消息'%s'發送成功,共發送了%d個字節!/n",  
  74.                buffer, len);  
  75.   
  76.     /* 關閉連接 */  
  77.     close(sockfd);  
  78.     return 0;  
  79. }  

編譯程序用下列命令:
gcc -Wall ipv6-server.c -o ipv6server
gcc -Wall ipv6-client.c -o ipv6client
你自己的主機有IPv6地址嗎?很多人會問,輸入ifconfig命令看一下吧:

eth0      鏈路封裝:以太網  硬件地址 00:14:2A:6D:5B:A5  
          inet 地址:192.168.0.167  廣播:192.168.0.255  掩碼:255.255.255.0
          inet6 地址: fe80::214:2aff:fe6d:5ba5/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  躍點數:1
          接收數據包:30507 錯誤:0 丟棄:0 過載:0 幀數:0
          發送數據包:26797 錯誤:0 丟棄:0 過載:0 載波:0
          碰撞:0 發送隊列長度:1000 
          接收字節:31461154 (30.0 MiB)  發送字節:4472810 (4.2 MiB)
          中斷:185 基本地址:0xe400 

lo        鏈路封裝:本地環回  
          inet 地址:127.0.0.1  掩碼:255.0.0.0
          inet6 地址: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  躍點數:1
          接收數據包:13 錯誤:0 丟棄:0 過載:0 幀數:0
          發送數據包:13 錯誤:0 丟棄:0 過載:0 載波:0
          碰撞:0 發送隊列長度:0 
          接收字節:1178 (1.1 KiB)  發送字節:1178 (1.1 KiB)
看到“inet6 地址:”這兩行了嗎?後面就是你的IPv6地址

啓動服務:
./ipv6server 7838 1
或者加上IP地址啓動服務:
./ipv6server 7838 1 fe80::214:2aff:fe6d:5ba5

啓動客戶端測試一下:
./ipv6client ::1/128 7838 

./ipv6client fe80::214:2aff:fe6d:5ba5 7838
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章