之前做过一次使用两台电脑传输数据,记录一下。
两台linux系统的电脑主机,各插上一块40G光纤模块,通过光纤连接。一台电脑发送数据,另一台接收数据。测试两台主机收发30Gbs没有问题。
1.为了支持40G光纤模块,首先需要安装驱动。
2.为了数据正常发送,建议关闭防火墙。
3.如果数据包很长,建议设置mtu。当然更长的数据包,会有更高校的传输效率。
问题记录及解决。
1.出现问题
接收端接收数据包丢包?
2.原因
通过更换不同的电脑主机发现,和电脑cpu的性能有关,cpu性能高的主机向cpu性能低的主机发送数据,接收端接收数据丢包。通过放缓发送端的速率可保证接收端不丢包。
发送端代码:
//
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <unistd.h>
#define CMD_LEN 20
const int LOCAL_PORT = 12368;
const int REMOTE_PORT = 12384;
// const char LOCAL_IP[]="192.168.11.101";
// const char REMOTE_IP[]="192.168.11.101";
const char LOCAL_IP[]="192.168.11.100";
const char REMOTE_IP[]="192.168.11.101";
const int MAXLINE = 2048;
const int WIDTH = 7680;
const int HEIGHT = 4320;
const unsigned char CMD_REQUEST_DATA_8K[CMD_LEN]={0x81,0x00,0xA5,0x5A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
int send_frame(int sockfd,struct sockaddr *pcliaddr, socklen_t clilen, unsigned char* dataptr)
{
static int count=0;
for(int i=0;i<HEIGHT;i++)
{
if(WIDTH != sendto(sockfd , dataptr, WIDTH , 0 , pcliaddr , clilen))
{
perror("sendto error");
exit(1);
}//if
dataptr += WIDTH;
}
count++;
printf("send a frame__%d\n",count);
if (count%10==0) //放缓发送速率。
{
usleep(1000000);
}
}
void clearRecvBuffer(int sockfd)
{
struct timeval time_out;
time_out.tv_sec=0;
time_out.tv_usec=0;
fd_set read_fds;
FD_ZERO(&read_fds);
FD_SET(sockfd,&read_fds);
int res=-1;
char recv_data[2];
memset(recv_data,0,sizeof(recv_data));
while (1)
{
res = select(FD_SETSIZE,&read_fds,NULL,NULL,&time_out);
if(res==0)
{
break;
}
recv(sockfd,recv_data,1,0);
}
}
void dg_echo(int sockfd , struct sockaddr *pcliaddr , socklen_t clilen)
{
int n;
unsigned char msg[CMD_LEN];
unsigned char* data = (unsigned char*)malloc(WIDTH*HEIGHT); //create the data of frame.
while(1)
{
if( CMD_LEN != recvfrom(sockfd , msg , CMD_LEN , 0 , NULL , NULL))
{
printf("recvfrom error\n");
//clearRecvBuffer(sockfd);
//exit(1);
}else{
printf("recv a request cmd\n");
}
if(msg[0]==0x81)
{
msg[0]=0;
send_frame(sockfd, pcliaddr,clilen,data);
}
}//while
}
int main(int argc , char **argv)
{
int sockfd,t;
struct sockaddr_in servaddr , cliaddr;
bzero(&cliaddr , sizeof(cliaddr));
cliaddr.sin_family = AF_INET;
//cliaddr.sin_addr.s_addr = htonl(INADDR_ANY);
cliaddr.sin_port = htons(REMOTE_PORT);
if((t = inet_pton(AF_INET , REMOTE_IP, &cliaddr.sin_addr)) <= 0)
{
perror("inet_pton error");
exit(1);
}//if
bzero(&servaddr , sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(LOCAL_PORT);
if((t = inet_pton(AF_INET , LOCAL_IP, &servaddr.sin_addr)) <= 0)
{
perror("inet_pton error");
exit(1);
}//if
if((sockfd = socket(AF_INET , SOCK_DGRAM , 0)) < 0)
{
perror("socket error");
exit(1);
}//if
int opt = 1;
setsockopt(sockfd, SOL_SOCKET,SO_REUSEADDR, (const void *) &opt, sizeof(opt));
//缓冲区设置
int err;
int snd_size = 35*1024*1024;
err = setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &snd_size, sizeof(snd_size));
if(err<0)
{
printf("set send buff failed!\n");
}
int rcv_size = 35*1024*1024;
err = setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF, (char *)&rcv_size, sizeof(rcv_size));
if(err<0){
printf("set rev buff failed!\n");
}
if(bind(sockfd , (struct sockaddr *)&servaddr , sizeof(servaddr)))
{
perror("bind error");
exit(1);
}//if
int n=0;
char mesg[1000];
if( (n= recvfrom(sockfd , mesg , 1000 , 0 , NULL , NULL))<0)
{
exit(1);
}else{
printf("recv a connection\n");
printf("recv: %s\n",mesg);
}
//设置超时20ms
// struct timeval tv;
// socklen_t optlen = sizeof(struct timeval);
// tv.tv_sec = 1; tv.tv_usec = 20000;
// setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, optlen);
printf("be ready to send frames-----------------.\n");
dg_echo(sockfd , (struct sockaddr *)&cliaddr, sizeof(cliaddr));
}
接收端代码
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <unistd.h>
#define CMD_LEN 20
const int LOCAL_PORT = 12384;
const int REMOTE_PORT = 12368;
const char LOCAL_IP[]="192.168.11.101";
const char REMOTE_IP[]="192.168.11.100";
//const char LOCAL_IP[]="127.0.0.1";
//const char REMOTE_IP[]="127.0.0.1";
const int MAXLINE = 2048;
const int WIDTH = 7680;
const int HEIGHT = 4320;
const unsigned char CMD_REQUEST_DATA_8K[CMD_LEN]={0x81,0x00,0xA5,0x5A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
void clearRecvBuffer(int sockfd)
{
struct timeval time_out;
time_out.tv_sec=0;
time_out.tv_usec=0;
fd_set read_fds;
FD_ZERO(&read_fds);
FD_SET(sockfd,&read_fds);
int res=-1;
char recv_data[2];
memset(recv_data,0,sizeof(recv_data));
while (1)
{
res = select(FD_SETSIZE,&read_fds,NULL,NULL,&time_out);
if(res==0)
{
break;
}
recv(sockfd,recv_data,1,0);
}
}
int recv_frame(int sockfd,struct sockaddr *pcliaddr, socklen_t clilen, unsigned char* dataptr)
{
static int count=0;
static int count_error=0;
int n=-1;
socklen_t len;
len = clilen;
count++;
for(int i=0;i<HEIGHT;i++)
{
if((n = recvfrom(sockfd , dataptr, WIDTH , 0 , pcliaddr , &len))<0)
{
count_error++;
printf("packet=%d ----------------recvfrom error=%d\n",i,count_error);
clearRecvBuffer(sockfd);
break;
}//if
dataptr += WIDTH;
}
printf("recv a frame__%d-------lost=%d\n",count,count_error);
}
void dg_echo(int sockfd , struct sockaddr *pcliaddr , socklen_t clilen)
{
int n;
// socklen_t len;
// len = clilen;
unsigned char *pdata = (unsigned char*)malloc(WIDTH*HEIGHT);
for( ; ;)
{
if((CMD_LEN != sendto(sockfd , CMD_REQUEST_DATA_8K , CMD_LEN , 0 , pcliaddr , clilen)))
{
perror("sendto error");
exit(1);
}else{
printf("send a request cmd.\n");
}
recv_frame(sockfd, pcliaddr, clilen,pdata);
}//for
}
int main(int argc , char **argv)
{
int sockfd,t;
struct sockaddr_in servaddr , cliaddr;
bzero(&cliaddr , sizeof(cliaddr));
cliaddr.sin_family = AF_INET;
//cliaddr.sin_addr.s_addr = htonl(INADDR_ANY);
cliaddr.sin_port = htons(REMOTE_PORT);
if((t = inet_pton(AF_INET , REMOTE_IP, &cliaddr.sin_addr)) <= 0)
{
perror("inet_pton error");
exit(1);
}//if
bzero(&servaddr , sizeof(servaddr));
servaddr.sin_family = AF_INET;
//servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(LOCAL_PORT);
if((t = inet_pton(AF_INET , LOCAL_IP, &servaddr.sin_addr)) <= 0)
{
perror("inet_pton error");
exit(1);
}//if
if((sockfd = socket(AF_INET , SOCK_DGRAM , 0)) < 0)
{
perror("socket error");
exit(1);
}//if
//ip地址重用
int opt = 1;
setsockopt(sockfd, SOL_SOCKET,SO_REUSEADDR, (const void *) &opt, sizeof(opt));
//超时设置
struct timeval tv;
int optlen = sizeof(struct timeval);
tv.tv_sec =0; tv.tv_usec = 30000;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, optlen);
//缓冲区设置
int err;
int snd_size = 35*1024*1024;
err = setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &snd_size, sizeof(snd_size));
if(err<0)
{
printf("set send buff failed!\n");
}
int rcv_size = 35*1024*1024;
err = setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF, (char *)&rcv_size, sizeof(rcv_size));
if(err<0){
printf("set rev buff failed!\n");
}
if(bind(sockfd , (struct sockaddr *)&servaddr , sizeof(servaddr)))
{
perror("bind error");
exit(1);
}//if
int n=0;
char mesg[]="hello";
if((n= sendto(sockfd , mesg , sizeof(mesg) , 0 , (struct sockaddr *)&cliaddr , sizeof(cliaddr)))<0)
{
perror("request connect,sendto error");
exit(1);
}
printf("be ready to get frames--------------------.\n");
dg_echo(sockfd , (struct sockaddr *)&cliaddr, sizeof(cliaddr));
}
|