我有一个设置,我通过串行或以太网连接从Windows笔记本电脑向Raspberry Pi发送数据(一次1个字节)。然后,Pi通过串行或以太网将数据发送回笔记本电脑,并记录往返时间的传输。 Raspberry Pi服务器使用C ++编写。
现在我正在尝试测量Raspberry Pi端接收和发送的执行时间。但是,我注意到相同的功能(在串行端口上接收)具有不同的执行时间,具体取决于是使用UDP还是TCP来发回数据。这对我来说没有意义,我认为无论如何在串口上接收都是一样的。
如有必要,我可以发布实际代码。谁能帮忙解释一下这里发生了什么?这是计时器的不准确吗?我正在使用chrono库进行毫秒计时。
以下是代码:
void send_client_udp( char *s, int mysock, int myport){
int i;
for(i=0;i<BACKLOG;i++){
if(htons(udparray[i].sin_port) == myport){
sendto(mysock,s,1,0,(struct sockaddr*)&udparray[i], sizeof udparray[i]);
}
}
}
void send_message_all_udp(char *s, int mysock){
int k;
for(k=0;k<BACKLOG;k++){
sendto(mysock,s,1,0,(struct sockaddr*)&udparray[k], sizeof udparray[k]);
}
}
void send_client_tcp( char *s, int mysock){
int i;
for(i=0;i<BACKLOG;i++){
if(tcparray[i]){
if(tcparray[i] == mysock){
send(tcparray[i], s, 1,0);
}
}
}
}
/* Send message to all clients */
void send_message_all_tcp(char *s){
int k;
for(k=0;k<BACKLOG;k++){
if(tcparray[k]){
send(tcparray[k], s, 1,0);
}
}
}
void *sr_es_udp(void *thissock)
{
int mysock = *(int*)thissock;
int counter = 1;
int ardint;
char ardchar;
char *mesg;
while (ardrun)
{
if (serialDataAvail (serfd) == -1)
{
fprintf(stdout, "(Serial) No data able to be received: %s\n", strerror (errno));
exit(EXIT_FAILURE);
}
auto recv1 = chrono::high_resolution_clock::now();
ardint = serialGetchar(serfd) ;
auto recv2 = chrono::high_resolution_clock::now();
if (ardint > 0)
{
ardchar = char(ardint);
mesg = &ardchar;
send_message_all_udp(mesg, mysock);
auto sendcli = chrono::high_resolution_clock::now();
std::chrono::duration<double,std::milli> elapscli = (sendcli - recv2);
std::chrono::duration<double,std::milli> elapsrecv = (recv2 - recv1);
outfile << counter << "\t" << elapsrecv.count() << "\t"<< elapscli.count() << "\t" << ardint << "\n";
counter++;
}
}
cout << "exit" << endl;
exitard= true;
}
void *er_es_udp(void *pnewsock)
{
int mysock = *(int*)pnewsock;
char client_msg[MAXLEN];
int read_size;
int clientint;
int myport;
int counter = 1;
while(looprun){
auto recv1 = chrono::high_resolution_clock::now();
read_size = recvfrom(mysock, client_msg, 1, 0, (struct sockaddr*)&their_addr, &size);
auto recv2 = chrono::high_resolution_clock::now();
clientint = int(*client_msg);
myport = htons(their_addr.sin_port);
if (clientint >0)
{
serialPuts (serfd, &(*client_msg)) ;
auto sendser = chrono::high_resolution_clock::now();
send_client_udp(client_msg,mysock,myport);
auto sendcli = chrono::high_resolution_clock::now();
std::chrono::duration<double,std::milli> elapsrecv = recv2-recv1;
std::chrono::duration<double,std::milli> elapscli = sendcli-recv2;
std::chrono::duration<double,std::milli> elapsser = sendser-recv2;
//outfile << counter << "\t" << elapsrecv.count() << "\t" << elapsser.count() << "\t" << clientint << "\n";
outfile << counter << "\t" << elapsrecv.count() << "\t" << elapscli.count() << "\t" << elapsser.count() << "\t" << clientint << "\n";
counter++;
}
}
cout << "exit " << endl;
}
/* TCP data handling */
void *sr_es_tcp(void *)
{
int counter = 1;
int ardint;
char ardchar;
char *mesg;
while (run)
{
if (serialDataAvail (serfd) == -1)
{
fprintf(stdout, "(Serial) No data able to be received: %s\n", strerror (errno));
exit(EXIT_FAILURE);
}
auto recv1 = chrono::high_resolution_clock::now();
ardint = serialGetchar (serfd) ;
auto recv2 = chrono::high_resolution_clock::now();
if (ardint > 0)
{
ardchar = char(ardint);
mesg = &ardchar;
send_message_all_tcp(mesg);
auto sendcli = chrono::high_resolution_clock::now();
std::chrono::duration<double,std::milli> elapscli = (sendcli - recv2);
std::chrono::duration<double,std::milli> elapsrecv = (recv2 - recv1);
outfile << counter << "\t" << elapsrecv.count() << "\t"<< elapscli.count() << "\t" << ardint << "\n";
counter++;
}
}
cout << "exit" << endl;
exitard=true;
}
/* handle the connections from client */
void *er_es_tcp(void *pnewsock)
{
int mysock = *(int*)pnewsock;
char client_msg[MAXLEN];
int read_size;
int clientint;
int myport;
int counter = 1;
while(looprun){
read_size = recv(mysock, client_msg, 1, 0);
auto recv2 = chrono::high_resolution_clock::now();
clientint = int(*client_msg);
if (clientint > 0)
{
client_msg[read_size] = '\0';
serialPuts(serfd, &(*client_msg)) ;
auto sendser = chrono::high_resolution_clock::now();
send_client_tcp(client_msg,mysock); //was send_message
auto sendcli = chrono::high_resolution_clock::now();
std::chrono::duration<double,std::milli> elapsrecv = recv2-recv1;
std::chrono::duration<double,std::milli> elapscli = sendcli-recv2;
std::chrono::duration<double,std::milli> elapsser = sendser-recv2;
outfile << counter << "\t" << elapscli.count() << "\t" << elapsser.count() << "\t" << clientint << "\n";
counter++;
}
}
cout << "exit " << endl;
}
对于sr_es函数,serialGetChar执行时间根据send_message_all是UDP还是TCP而变化。 serialGetChar来自WiringPi串行库。另外,Eth_recv_eth_send()中的send_message_client_tcp对于TCP的Ser_recv_eth_send()中的send_message_all_tcp是不同的,特别是当serialGetChar以115200bps接收时,与9600bps相比。为什么会这样?只有一个客户端,因此send_message_client_tcp()和send_message_all_tcp()应该相同。无论串口波特率如何,都不应该发送tcp一致,为什么串口接收时间因互联网协议而改变?
以下是几项不同测试的平均值和标准偏差(每次1000个数据点的10次试验):
通过以太网接收/发送
系列接收,通过以太网发送