c++ - 使用UDP进行写入和读取之间的长时间延迟

标签 c++ raspberry-pi udp client-server labview

我有一个运行C++程序的Raspberry Pi 4,它通过UDP接收和发送数据。 RPi被设置为UDP服务器。

UDP.hpp的代码是:

#pragma once

#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string>

using namespace std;

/////GLOBAL CONSTANTS/////
const int c_PORT = 8080;

class UDP
{
private:
    int fdSocketUDP_;                  //File descriptor for UDP socket
    int ClientAddressLength_;          //Length of client address
    struct sockaddr_in ServerAddress_; //Struct handling internet address for server
    struct sockaddr_in ClientAddress_; //Struct handling internet address for client

public:
    UDP();                              //Initialize and bind socket
    ~UDP();                             //Close socket
    string readUDP(const int readSize); //Read via UDP protocol
    void writeUDP(string message);      //Write via UDP protocol
};

UDP.cpp的代码是:
#include "udp.hpp"

UDP::UDP()
{
    if ((fdSocketUDP_ = socket(AF_INET, SOCK_DGRAM, 0)) < 0) //Create UDP socket
    {
        perror("Error - socket creation - udp.cpp");
        exit(EXIT_FAILURE);
    }
    memset(&ServerAddress_, 0, sizeof(ServerAddress_)); //Sets ServerAddress_ to 0
    memset(&ClientAddress_, 0, sizeof(ClientAddress_)); //Sets ClientAddress_ to 0

    ServerAddress_.sin_family = AF_INET;         //Address family, must be AF_INET = IPv4
    ServerAddress_.sin_port = htons(c_PORT);     //PORT number, convert PORT number to network byte order using htons()
    ServerAddress_.sin_addr.s_addr = INADDR_ANY; //IP-Address of host (server IP), INADDR_ANY gets this IP Address

    if (bind(fdSocketUDP_, (const struct sockaddr *)&ServerAddress_, sizeof(ServerAddress_)) < 0) //Bind the socket to ServerAddress_
    {
        perror("Error - socket bind - udp.cpp");
        exit(EXIT_FAILURE);
    }
}

UDP::~UDP()
{
    close(fdSocketUDP_); //Close socket
}

string UDP::readUDP(const int readSize)
{
    char readMsg[readSize] = {0}; //Read buffer
    ClientAddressLength_ = sizeof(ClientAddress_);

    if ((recvfrom(fdSocketUDP_, readMsg, readSize, 0, (struct sockaddr *)&ClientAddress_, (socklen_t *)&ClientAddressLength_)) < 0) //Receive data via UDP protocol
    {
        perror("Error - recvfrom - udp.cpp");
        exit(EXIT_FAILURE);
    }

    string str(readMsg);           //Convert char array to string
    str = str.substr(0, readSize); //Make sure the string is the length of readsize
    return str;
}

void UDP::writeUDP(string message)
{
    //Make char array
    int writeSize = message.size();
    char writeMsg[writeSize + 1] = {'\0'};

    //Convert string message to char array
    for (int i = 0; i < writeSize; i++)
    {
        writeMsg[i] = message[i];
    }

    if ((sendto(fdSocketUDP_, writeMsg, writeSize, 0, (const struct sockaddr *)&ClientAddress_, (socklen_t)ClientAddressLength_)) < 0) //Send data via UDP protocol
    {
        perror("Error - sendto - udp.cpp");
        exit(EXIT_FAILURE);
    }
}

然后,我有一台Windows 10笔记本电脑,运行Labview程序,该程序也通过UDP接收和发送数据。便携式计算机设置为UDP客户端。以下是Labview中UDP设置的示例。

图像1(开放UDP连接):

Open UDP socket connection in Labview

图片2(关闭UDP连接):

Close UDP socket connection in Labview

图像3(在Labview中写入和读取UDP):Example of a Labview function that writes data to RPi and the receives (16 byte) data from RPi

上面,笔记本电脑上的Labview程序向RPi发送3(“103”)+ 37(未显示)字节的数据,然后从RPi接收16字节的数据。

笔记本电脑和RPi通过局域网上的局域网电缆连接。 RPi使用IP地址10.10.10.10和端口8080,而笔记本电脑使用IP地址10.10.10.1和端口1000。

以下是Wireshark测量,它测量RPi和笔记本电脑之间不同的发送和接收命令之间的时间。

图4(wireshark测量):

Wireshark measurement

RPi使用“Len = 3”来确定要在C++代码中运行的函数。 “Len = 52”和“Len = 37”是从便携式计算机(Labview)发送到RPi(C++代码)的数据。 “Len = 16”是从RPi发送到笔记本电脑的数据。

便携式计算机首先将3 + 52字节的数据发送到RPi(客户端将数据发送到服务器)。然后,笔记本电脑将3 + 37字节的数据发送到RPi(客户端将数据发送到服务器)。然后,RPi将16字节的数据发送回膝上型计算机(服务器将数据发送到客户端)...依此类推。

一个命令(3 + 52字节或3 + 37 + 16字节)大约需要8毫秒才能完成,而每个命令之间的延迟(平均)约为2毫秒。如您所见,RPi和便携式计算机之间的数据大小“相对”较小(3/37/52字节)。

现在是我的问题:有时命令之间会有〜20ms的延迟(比〜2ms的平均值长10倍),我不知道为什么...(这在图4上用红点显示)。这种延迟通常是在RPi(UDP服务器)将数据发送到便携式计算机(UDP客户端-16字节数据)之后发生的,但是它可能发生在不同的地方,如图4所示(在便携式计算机向RPi发送52个字节之后) )。我认为这与UDP有关,也许与设置有关,也许与ARP有关,但我不知道。我尝试对RPi超频,调整RPi上C++程序的优先级,调整C++代码,但这似乎不是瓶颈。

就像笔记本电脑和RPi之间的UDP连接有时“丢失”或“暂停”,然后需要一些时间才能使连接恢复正常。

最佳答案

我找到了解决问题的办法。为了解决长时间的延迟,我不得不降低UDP读取缓冲区,因为我只通过UDP发送小数据包。
为此,我在/ etc文件夹中的RPi上格式化了sysctl.conf文件。
我添加了以下行:
net.core.rmem_default = 4096
net.core.rmem_max = 4096

关于c++ - 使用UDP进行写入和读取之间的长时间延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62325907/

相关文章:

c++ bool模板避免if语句

python - 从 Raspberry PI 运行时不显示 Dash/Plotly 图表

javascript - 事件页面卸载后,没有在 Chrome 上获取 UDP 套接字的 onReceive 回调

c - 如何通过UDP套接字进行广播?

python - 在 Python 中读取 UDP 数据包的缓冲区大小

c++ - 如何在不转换回基类类型的情况下返回其派生类型的对象?

C++智能指针循环链接

c++ - 如何覆盖 exit(),可能是通过抛出异常

c++ - {生成文件错误} "commands commence before first target. Stop."

c++ - Raspberry 交叉编译的链接器错误