【Socket编程】Linux下的IPv6 socke编程

该网站(点击打开链接)提供了一些Linux下的IPv6的tcp/udp socket编程范例,然而经过测试发现这些实例都只能用于同一台机器间的客户端、服务器通信,当在两台机器间使用link-local地址进行通信时,可ping通,然而客户端通过connectI()无法连接上服务器,被该问题困扰许久。之后在StackOverflow找到了答案。点击打开链接

现在将tcp 的IPv6服务器、客户端编程说明如下:

一、服务器编程遵循以下流程:1、创建套接字

int socket(int domain, int type, int protocol)

该函数用于创建一个socket描述符,可唯一标识一个套接字,参数domain代表协议域,这里使用PF_INET6, type可设置是使用tcp还是udp,这里使用SOCK_STREAM,参数protocol这里不使用

2、绑定套接字

将服务端的IP地址、端口号与socket套接字进行绑定,用以给客户端提供服务,可用int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen)进行绑定

3、监听套接字可调用该函数int listen(int sockfd, int backlog)进行监听,当客户端发出connect()函数时,服务器会调用accept()接收该请求。参数sockfd为套接字标识符,backlog为可接收的最大连接数。4、接收请求当客户端发起connect()请求时,服务器监听到该请求,会调用accept()函数接收请求。函数原型为int accept4(int sockfd, struct sockaddr *addr,socklen_t *addrlen, int flags); sockfd为套接字描述符,addr 为客户端的IP地址与端口号。

接下来完成网络IO操作即可。

以下为代码

#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>#define PORT 12345#define MESSAGE "hello"int main(void){  int sock, conn;  socklen_t clilen;  struct sockaddr_in6 server_addr, client_addr;  char addrbuf[INET6_ADDRSTRLEN];  /* create a STREAM (TCP) socket in the INET6 (IPv6) protocol */  sock = socket(PF_INET6, SOCK_STREAM, 0);  if (sock < 0) {    perror("creating socket");    exit(1);  }#ifdef V6ONLY  // setting this means the socket only accepts connections from v6;  // unset, it accepts v6 and v4 (mapped address) connections{ int opt = 1;    if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) < 0) {      perror("setting option IPV6_V6ONLY");      exit(1);    }  }#endif  /* create server address: this will say where we will be willing to     accept connections from */  /* clear it out */  memset(&server_addr, 0, sizeof(server_addr));  /* it is an INET6 address */  server_addr.sin6_family = AF_INET6;  /* the client IP address, in network byte order */  /* in this example we accept connections from ANYwhere */  server_addr.sin6_addr = in6addr_any;  /* the port we are going to listen on, in network byte order */  server_addr.sin6_port = htons(PORT);  /* associate the socket with the address and port */  if (bind(sock, (struct sockaddr *)&server_addr,           sizeof(server_addr)) < 0) {    perror("bind failed");    exit(2);  }  /* start the socket listening for new connections */  if (listen(sock, 5) < 0) {    perror("listen failed");    exit(3);  }  while (1) {    /* now wait until we get a connection */    printf("waiting for a connection...\n");    clilen = sizeof(client_addr);    conn = accept(sock, (struct sockaddr *)&client_addr, &clilen);    if (conn < 0) {  perror("accept failed");      exit(4);    }    /* now client_addr contains the address of the client */    printf("connection from %s\n",           inet_ntop(AF_INET6, &client_addr.sin6_addr, addrbuf,                     INET6_ADDRSTRLEN));    printf("sending message\n");    write(conn, MESSAGE, sizeof(MESSAGE));    /* close connection */    close(conn);  }    return 0;}

二、客户端编程遵循以下流程

1、创建套接字

这个跟服务器端socketI()函数一样

2、连接服务器

客户端可用connect()函数连接服务器,服务器在监听到该连接请求时,可接受该请求。

由于IPv6中引入了 scope id域,这里需用到getaddrinfo()函数,该函数可实现IP地址、端口到addrinfo结构体的转换,具体说明日后补充。吃饭中。。。

看代码

#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <sys/types.h>#include <sys/socket.h>#include <netdb.h>#define PORT "12345"#define SERVADDR "fe80::223:8bff:fe59:de90%wlan0"int main(void){        struct addrinfo hints = {0};        struct addrinfo *res;        int get_err;        int sockfd;        char buffer[1024];        hints.ai_family = AF_INET6;        hints.ai_socktype = SOCK_STREAM;        get_err = getaddrinfo(SERVADDR, PORT, &hints, &res);        if(get_err)        {                fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(get_err));                return 1;        }        sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);        if(sockfd < 0)        {                perror("socket");                return 1;        }        if(connect(sockfd, res->ai_addr, res->ai_addrlen) < 0)        {                perror("connect");                return 1;        }        printf("reading message\n");        read(sockfd, buffer, 1024);        printf("got '%s'\n", buffer);        close(sockfd);        return 0;}

我想有一天和你去旅行。去那没有去过的地方,

【Socket编程】Linux下的IPv6 socke编程

相关文章:

你感兴趣的文章:

标签云: