万兆网络UDP速率传输性能测试(发送端)

客户端代码运行平台是在Linux,开发平台是在Debian上交叉编译,采取多线程发送数据,并且将每个线程绑定到每个核上,这样最大性能发挥CPU的处理速度,万兆网络传输速率测试结果达到920MByte/s,这个速度接近极限了。写代码遇到了一些问题,虽然比较简单,下面我会说明的。代码如下:


遇到问题:

(1)  添加头文件#include <sched.h>还是提示找不到这个文件里面的宏定义,打开头文件发现需要定义#define __USE_GNU这个宏,最开始我定义在代码头文件最开始出,编译还是提示找不到,后来解决问题发现需要定义在#include <sched.h>这个头文件之前,中途的其他的头文件很有可能已经取消定义了,所以需要定义在#include <sched.h>文件之前。

(2)这个错误犯的有点低级,memset((char *)ucSendBuf, 'b', ONCE_SIZE);最开始我直接赋值为一,没有加引号,服务端接受数据总是为空,打印不出来。后来发现,当赋值为1的时候,这个ASCILL码是打印不出来的,如果需要发送数字1,需要'1'这样写,这样才是取数字1的ASCALL码


Udp_client.c

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <time.h>
#include <sys/mman.h>
#include <semaphore.h>
#define __USE_GNU
#include <sched.h>


#define ONCE_SIZE  61440   /* 60k */

#define Cycle_Time   (1024*1024)

//#define DBG_PRINTF  printf
#define DBG_PRINTF(...)

struct Socket_Pagram
{
	int SockFd;
	int Thread_Num;
	unsigned char *buff_addr;
	double TimeTotal;
	pthread_t   ID;
	struct sockaddr *Addr; 
};


#if 1     /* 线程绑定核940.992606Mb/s */
void *mythread(struct Socket_Pagram *ptr)
{
	int n=Cycle_Time,i;
	time_t Time_Start,Time_End;

	cpu_set_t  mask,get;

	int num = sysconf(_SC_NPROCESSORS_CONF);

	printf("system has %d processor\n",num);

	CPU_ZERO(&mask);
	CPU_SET(ptr->Thread_Num,&mask);

	if(sched_setaffinity(0, sizeof(mask),&mask)==-1);
	{
		printf("warning:could not set CPU affinity\n");
	}

	CPU_ZERO(&get);
	if(sched_getaffinity(0, sizeof(get),&get)==-1);
	{
		printf("warning:could not get CPU affinity\n");
	}

	for(i=0;i<num;i++)
	{
		if(CPU_ISSET(i,&get))
		{
			printf("this thread %d is running processor :%d\n",ptr->Thread_Num,i);
		}
	}
	Time_Start = clock();
	while(n--) 
	{ 		
		sendto(ptr->SockFd,(const void *)ptr->buff_addr,ONCE_SIZE,0,ptr->Addr,sizeof(struct sockaddr_in)); 
	}
	Time_End = clock();	
	ptr->TimeTotal = (double)(Time_End-Time_Start)/CLOCKS_PER_SEC;	

	DBG_PRINTF("thread num %d  run time is:%f\n ",ptr->Thread_Num,ptr->TimeTotal);
	
	return;
} 

#else  /* 573.049596 */
void *mythread(struct Socket_Pagram *ptr)
{
	int n=Cycle_Time,i=0;
	time_t Time_Start,Time_End;

	Time_Start = clock();
	while(n--) 
	{ 		
		sendto(ptr->SockFd,(const void *)ptr->buff_addr,ONCE_SIZE,0,ptr->Addr,sizeof(struct sockaddr_in)); 
	}
	Time_End = clock();	
	ptr->TimeTotal = (double)(Time_End-Time_Start)/CLOCKS_PER_SEC;	

	DBG_PRINTF("thread num %d  run time is:%f\n ",ptr->Thread_Num,ptr->TimeTotal);
	
	return;
} 
#endif

void print_usage(char *file)
{
	printf("Usage:\n");
	printf("%s <server IP > <server Port > <Self_Thread Nums>\n", file);
}

int main(int argc,char **argv) 
{ 
	int sockfd; 
	struct sockaddr_in addr; 

	double speed,All_Speed = 0,All_Time = 0;

	int ret,n,i,iRet,port;  

	int Thread_Nums = 5;  /* Default thread nums is 5s */
	
	struct Socket_Pagram *Pagram;

	char *buff = "send is complete";

	char *ucSendBuf = NULL;

	if (argc != 4) 
	{
		print_usage(argv[0]);
		return -1;
	}

	Thread_Nums = strtoul(argv[3], NULL, 0);

	port = strtoul(argv[2], NULL, 0);

	Pagram = (struct Socket_Pagram *)malloc(Thread_Nums*sizeof(struct Socket_Pagram));
	
	ucSendBuf = (char *)malloc(ONCE_SIZE);
	if(ucSendBuf == NULL)
	{
		return 1;
	}
	memset((char *)ucSendBuf, 'b', ONCE_SIZE);
	
	sockfd=socket(AF_INET,SOCK_DGRAM,0); 
	if(sockfd<0) 
	{ 
		printf("Socket Error:%s\n"); 
		return -1; 
	} 

	bzero(&addr,sizeof(struct sockaddr_in)); 
	addr.sin_family=AF_INET; 
	addr.sin_port=htons(port);
	
	if(inet_aton(argv[1],&addr.sin_addr)<0)  
	{ 
		printf("Ip error:%s\n"); 
		return -1; 
	} 


	for(i=0;i<Thread_Nums;i++){
		Pagram[i].Addr               = (const struct sockaddr *)&addr;
		Pagram[i].buff_addr       = ucSendBuf;
		Pagram[i].SockFd           =  sockfd;
		Pagram[i].TimeTotal       = 0;
		Pagram[i].Thread_Num  = i+1;
	}

	for(i=0;i<Thread_Nums;i++){
		ret=pthread_create(&Pagram[i].ID,NULL,(void*)mythread,&Pagram[i]);
		if(ret)
		{
			printf("create pthread %d error!\n",Pagram[i].Thread_Num);

			return -1; 
		}

	}

	for(i=0;i<Thread_Nums;i++){
		pthread_join(Pagram[i].ID,NULL);
	}
	sendto(sockfd,(const void *)buff,strlen(buff),0,(const struct sockaddr *)&addr,sizeof(struct sockaddr_in));

	for(i=0;i<Thread_Nums;i++){
		All_Speed += (double)(ONCE_SIZE)/Pagram[i].TimeTotal;
	}

	for(i=0;i<Thread_Nums;i++){
		All_Time += Pagram[i].TimeTotal;
	}
	
	printf("Program  run time :%f seconds\n",All_Time/Thread_Nums);
	printf("Net peed is:%f Mb/s\n",All_Speed);

	close(sockfd); 

} 


下篇文章将介绍写服务端接受程序,接受端是在VS2010上编写的控制台应用程序。


更正:

将clock()函数更改为如下:

#include <sys/time.h>
long  get_ms()
{
struct timeval t;
long tick;
gettimeofday(&t,0);
tick=(long)(t.tv_sec)*1000+(long)(t.tv_usec)/1000;
return tick;
}


                                                                                                         By  Design :Linux_Google

猜你喜欢

转载自blog.csdn.net/qq_21792169/article/details/77403046