zoukankan      html  css  js  c++  java
  • 一对简单的IPV6 SOCKET代码

    一对简单的IPV6 SOCKET代码,包括服务端ipv6_server.c及客户端ipv6_client.c

    服务端ipv6_server.c

    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <errno.h>
    #include <stdio.h>
    
    #define MAXLINE 1024
    
    int main(int argc, char **argv)
    {
       int listenfd, connfd;
       socklen_t len;
       char buff[MAXLINE];
       struct sockaddr_in6	servaddr, cliaddr;
       //第一个参数指定AF_INET6来创建一个ipv6监听套接字
       listenfd = socket(AF_INET6, SOCK_STREAM, 0);
    
       bzero(&servaddr, sizeof(servaddr));
       //servaddr的地址族指定AF_INET6
       servaddr.sin6_family = AF_INET6;
       //地址使用通配符
       servaddr.sin6_addr = in6addr_any;
       //端口使用9999
       servaddr.sin6_port = htons(9999);
    
       bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
       listen(listenfd, 1);
    
       for ( ; ; ) 
       {
          len = sizeof(cliaddr);
          connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &len);
          sprintf(buff, "hello");
          write(connfd, buff, strlen(buff));
          close(connfd);
    	}
    }
    

    需要注意的是,在ipv4中,地址通配符可以直接使用0来赋值,即
    servaddr.sin_addr.s_addr = 0
    而在ipv6的编程中不能用0直接赋值,原因是ipv6的地址是存放在一个长度为16的unit8_t数组中的。

    客户端ipv6_client.c

    #include <unistd.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    #include <stdio.h>
    #include <netdb.h>
    
    #define MAXLINE 1024
    
    void mygetaddinfo(struct sockaddr_in6 *servaddr, char *addr)
    {
       struct addrinfo *ai, *hints;
       memset(hints, 0, sizeof(struct addrinfo));
       //只要ipv6地址族的结果
       hints->ai_family = AF_INET6;
       if((getaddrinfo(addr, "9999", hints, &ai)) != 0)
       {
          perror("IN GETADDRINFO()");
          exit(1);
       }
       *servaddr = *(struct sockaddr_in6 *)ai->ai_addr;
       //指定使用的接口
       servaddr->sin6_scope_id = 2;
    }
    
    int main(int argc, char **argv)
    {
       int sockfd, n;
       struct sockaddr_in6 servaddr;
       char recvline[MAXLINE];
       socklen_t len;
       if (argc != 2)
       {
          printf("INPUT ADDRESS!");
          exit(1);
       }
    
       if ( (sockfd = socket(AF_INET6, SOCK_STREAM, 0)) < 0)
       {
          perror("SOCKET");
          exit(1);
       }
       bzero(&servaddr, sizeof(servaddr));
       mygetaddinfo(&servaddr, argv[1]);
    
       len = sizeof(servaddr);
       if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)
       {   
          perror("CONNEXT");
          exit(1);
       }
    
       n = read(sockfd, recvline, MAXLINE);
       recvline[n] = 0;
       printf("%s
    ", recvline);
       exit(0);
    }
    

    在客户端的代码中,使用了getaddrinfo(char *, char *, struct addrinfo *, struct addrinfo **)来获取服务端的sockaddr_in6结构体(如果已有地址串及已确定的端口,这调用并没有必要)。值得注意的是,如果使用的链路本地地址(Link-Local Address,以fe80:打头),则必须指定sockaddr_in6中的sin6_scope_id成员,其成员的值可以通过ip link命令获得,为对应接口前的数字:

    sunminming@sunminming:~$ ip link   
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00   
    2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000 link/ether 08:00:27:47:bc:c8 brd ff:ff:ff:ff:ff:ff   
    

    如果使用的ipv6的环回地址::1也可以不用指定sin6_scope_id成员。

  • 相关阅读:
    【leetcode】1403. Minimum Subsequence in Non-Increasing Order
    【leetcode】1399. Count Largest Group
    【leetcode】1396. Design Underground System
    【leetcode】1395. Count Number of Teams
    【leetcode】1394. Find Lucky Integer in an Array
    【leetcode】1391. Check if There is a Valid Path in a Grid
    【leetcode】1390. Four Divisors
    【leetcode】1389. Create Target Array in the Given Order
    modelsim仿真基本流程
    Quartus调用MOdelsim仿真过程
  • 原文地址:https://www.cnblogs.com/sunminming/p/12288991.html
Copyright © 2011-2022 走看看