【开源夏令营第六周】IPv6的测试

来源:互联网 发布:淘宝衣服款式怎么设置 编辑:程序博客网 时间:2024/05/16 02:01

本周对LwIP的IPv6的socket编程接口与netconn API接口进行了测试,验证了IPv6的功能,并对协议栈进行了压力测试。

1、socket API 测试

1.1 socket API 实现概况

LwIP 实现了绝大多数的BSD Socket 的IPv6接口,可不做特别多的改动即可将其他Linux发行版中的Socket程序移植在RT-Thread+LwIP中,然而仍有一些接口函数并未完整实现,如getaddrinfo(),
这就导致了在其他Linux发行版中编写的基于getaddrinfo()函数的TCP/UDP client无法很好地移植到lwip中。我们使用了inet_pton()函数将字符串转换为网络字节顺序。

1.2 IPv6 Socket API介绍

1、inet_pton()函数

函数原型:inet_pton(int family, const char *strptr, void *addrptr)
p代表表达式(presentation),n代表数值(numeric),用于转换由strptr指向的字符串,并通过addrptr指针存放二进制结果。成功返回1,否则如果对所指定的family而言输入的字符串不是有效的表达式,那么返回值为0
参数family既可以是AF_INET,又可以是AF_INET6,如果以不被支持的地址族作为family参数,那么该函数将返回错误,并将errno置为EAFNOSUPPORT.

2、getaddrinfo()函数

gethostbyname()、gethostbyaddr()函数仅仅支持IPv4,而IPv6中使用getaddrinfo()函数来替代,该函数能够处理名字到地址、服务到端口的转换,返回一个sockaddr结构。返回的信息可供后面的套接字函数来使用
函数原型
int lwip_getaddrinfo(const char *nodename, const char *servname,
        const struct addrinfo *hints, struct addrinfo **res)
参数res是一个指向addrinfo结构体的指针。其定义如下:
struct addrinfo {    int               ai_flags;      /* Input flags. */    int               ai_family;     /* Address family of socket. */    int               ai_socktype;   /* Socket type. */    int               ai_protocol;   /* Protocol of socket. */    socklen_t         ai_addrlen;    /* Length of socket address. */    struct sockaddr  *ai_addr;       /* Socket address of socket. */    char             *ai_canonname;  /* Canonical name of service location. */    struct addrinfo  *ai_next;       /* Pointer to next in list. */};,
参数nodename是一个主机名或者是地址串(IPv4的十进制串或者IPv6的十六进制串),servname为服务名或者端口号
hints为一个指向某个addrinfo结构的指针,该结构体带有协议族、TCP/UDP类型的信息

3、gai_strerror()函数

该函数用以返回getaddrinfo()返回的错误值得信息。LwIP并未实现。

4、void lwip_freeaddrinfo(struct addrinfo *ai);

由于getaddrinfo()所返回的存储空间是动态获取的,因而需要调用freeaddrinfo()函数来释放空间。

1.3 Socket API 编写流程

这里编写的是单线程的阻塞的TCP Server/Client , UDP Server/Client测试程序。
注意以下的{}表示循环

1、TCP Server

socket()->bind()->listen()->{accept()->{send()->recv()(直到客户端断开)}(直到关闭)}

2、TCP Client

socket()->inet_pton()->connect()->{recv()->send()}

3、UDP Server

socket()->bind()->{recvfrom()->sendto()}

4、UDP Client

socket()->inet_pton()->sendto()->recvfrom()
这几个基于Socket API的代码就不粘贴出来,具体的代码今后将Pull Request到RT-Thread上。
当然也编写了基于多线程的tcp/udp 服务器与基于select的I/O 复用的服务器,这里就不具体说明了

1.4 测试环境与方法

运行着RT-Thread2.0.0 + LwIP-head的MB9BF618S开发板与支持IPv6协议的路由器相连,将Linux主机与路由器相连,Linux主机所用代码见点击打开链接,这里只进行通断性测试,这里不截图了,Linux主机现在还在做压力测试。

2、协议栈的压力测试

协议栈的压力测试的基本的思路为模拟真实环境的数据包对协议栈进行长时间的通信测试,模拟真实环境这里使用到了产生随机字符串的办法,

2.1 Linux下产生随机字符串

主要用到的函数有srand()函数与rand()函数。rand()函数会返回一个随机数,其值范围在0 到RAND_MAX之间,当然在调用rand()函数前需要调用srand()函数产生随机数种子,以下是产生随机字符串的代码:
</pre></div><pre name="code" class="cpp">void get_rand_str(char str[],int number){    char standstr[64] = "00123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";//参考字符串    int i;    char genstr[2];    srand((unsigned int)time((time_t *)NULL));//生成随机数种子    for(i = 1; i <= number; i++){        sprintf(genstr,"%c",standstr[(rand()%62)+1]);//生成随机字符    strcat(str,genstr);    }}

2.2服务器和客户端的设计

服务器为单线程的阻塞的基于Socket的TCP回显服务器,当accept()到连接后就一直不断的收发数据。
客户端为单线程的阻塞的基于Socket的tcp 客户端,当connect()成功后就一直不断的收数据发数据,客户端发送的数据是在1到1000之间的随机长度的随机字符串,目前测试已进行10多小时,收发数据正常,服务器TCP 状态正常。



0 0
原创粉丝点击