将龙芯2F笔记本作为TCP Client,开发板作为 TCP Server
笔记本构造随机长度(长度在1-1000之间)的随机字符串,TCP Server作为回显服务器
利用单线程的阻塞模型,测试了3*24小时 一切收发正常,发送420658个字符串,接收420658个字符串,平均来看一个字符串有0.5KB.
Client端的测试代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define PORT "10001"
#define SERVADDR "fe80::200:eff:fe12:3456%eth1"
//static const char send_data[] = "This is TCP Client from Debian.";
void setrandstr(char str[], int number);
int main(void)
{
struct addrinfo hints = {0};
struct addrinfo *res;
int get_err;
int sockfd;
int sendnum, recvnum;
int number;
char send_data[1024];
char buffer[1024];
int enable = 1;
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;
}
setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (void *)&enable, sizeof(enable));
if(connect(sockfd, res->ai_addr, res->ai_addrlen) < 0)
{
perror("connect");
return 1;
}
sendnum = 0; recvnum = 0;
while(1)
{
//随机产生字符串的长度
srand((unsigned int)time((time_t *)NULL));
number = (rand() % 999) + 1;
// printf("%d\n", number);
setrandstr(send_data, number);
printf("%s\n", send_data);
send(sockfd, send_data, strlen(send_data), 0);
sendnum ++;
printf("reading message\n");
memset(send_data, 0, sizeof(send_data));
read(sockfd, buffer, 1024);
recvnum++;
printf("got '%s', sendnum:%d, recvnum:%d\n", buffer, sendnum, recvnum);
memset(buffer, 0, sizeof(buffer));
}
close(sockfd);
return 0;
}
// 产生随机字符串
void setrandstr(char str[], int number)
{
char standard[64] = "00123456789ABCDEFGHIGKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
char genstr[2];
int i;
srand((unsigned int)time((time_t *)NULL));
for(i = 0; i< number; i++)
{
sprintf(genstr, "%c", standard[(rand()%62+1)]);
strcat(str, genstr);
}
str[number] = '\0';
// printf("%s\n", str);
}
Server的测试代码如下:
#include
#include
#define SERV_PORT 10001
#define BUF_SIZE 1024
#define BACKLOG 5
//static const char send_data[] = "This is TCP Server from RT-Thread.";
void tcp_robust_test(void *parameter)
{
int sockfd, clientfd;
struct sockaddr_in6 server_addr6, client_addr6;
int bytes_received;
char *recv_data;
rt_uint32_t sin_size;
rt_bool_t stop = RT_FALSE;
// recv_data = rt_malloc(BUF_SIZE);
// if(recv_data == RT_NULL)
// {
// rt_kprintf("No memory\n");
// return ;
// }
if((sockfd = socket(PF_INET6, SOCK_STREAM, 0)) == -1)
{
rt_kprintf("Socket error\n");
// rt_free(recv_data);
return ;
}
server_addr6.sin6_family = AF_INET6;
memcpy(server_addr6.sin6_addr.s6_addr, IP6_ADDR_ANY, 16);
server_addr6.sin6_port = htons(SERV_PORT);
if(bind(sockfd, (struct sockaddr *)&server_addr6, sizeof(struct sockaddr)) == -1)
{
rt_kprintf("Bind error\n");
// rt_free(recv_data);
return ;
}
if(listen(sockfd, BACKLOG) == -1)
{
rt_kprintf("Listen error\n");
// rt_free(recv_data);
return ;
}
// rt_sprintf(recv_data, "%4d", SERV_PORT);
// rt_kprintf("\nTCPServer Waiting for client on port %s...\n", recv_data);
while(stop != RT_TRUE)
{
sin_size = sizeof(struct sockaddr_in6);
clientfd = accept(sockfd, (struct sockaddr *)&client_addr6, &sin_size);
rt_kprintf("I got a connection from (IP:%s, PORT:%d\n)", inet6_ntoa(client_addr6.sin6_addr), ntohs(client_addr6.sin6_port));
while(1)
{
recv_data = rt_malloc(BUF_SIZE);
if(recv_data == RT_NULL)
{
rt_kprintf("No memory\n");
return ;
}
// send(clientfd, send_data, strlen(send_data), 0);
bytes_received = recv(clientfd, recv_data, BUF_SIZE, 0);
if(bytes_received <= 0)
{
closesocket(clientfd);
break;
}
recv_data[bytes_received] = '\0';
// if(strcmp(recv_data, "q") == 0 || strcmp(recv_data, "Q") == 0)
// {
// closesocket(clientfd);
// break;
// }
// else if(strcmp(recv_data, "exit") == 0)
// {
// closesocket(clientfd);
// stop = RT_TRUE;
// break;
// }
// else
// {
//// rt_kprintf("RECEIVED DATA = %s\n", recv_data);
// }
send(clientfd, recv_data, strlen(recv_data), 0);
rt_free(recv_data);
// memset(recv_data, 0, sizeof(recv_data));
}
}
closesocket(sockfd);
rt_free(recv_data);
return ;
}
int tcp_robust_init()
{
rt_thread_t tid = RT_NULL;
tid = rt_thread_create("tcpserver", tcp_robust_test, RT_NULL, 4096, 19, 1);
if(tid != RT_NULL)
{
rt_kprintf("tcp robust test server init ok\n");
rt_thread_startup(tid);
return 0;
}
else
{
rt_kprintf("tcp robust test server init failed\n");
return -1;
}
}
要写ping 的程序必须使用BSD 原始套接字,原理为:某一主机向网络上主机发送ICMP请求报文,如果系统得到了报文会将报文一模一样的传给发送者。在ipv6中须使用icmpv6过滤器,因为相邻的主机会发来邻居请求报文,这是ICMPV6类型的,如下所示:
但是lwip-head并未实现如下icmpv6过滤器
但是可以根据接收到的pid号来判断是否是本主机发出的icmp request包的反馈。
未完待续。。