c - 与 iperf UDP 性能相比,UDP 吞吐量较低

标签 c sockets networking udp iperf

当通过 iperf2 工具测量 Windows PC 和基于 Zynq 的设备之间的 UDP 吞吐量时,我通过专用 1Gb 以太网链路获得了大约 950 Mb/s 的吞吐量。然而,当在 PC 上使用我自己的 UDP 应用程序时,我只能获得大约 50 Mb/s,这比 iperf 测量的吞吐量要低得多。当然,在我的 UDP 应用程序中,我没有任何处理,只有 while 循环,我在其中调用 sendto 函数,UDP 数据包大小为 1470 字节。 Zynq 设备上的应用程序由 XAPP1026 提供,因此不是我的。我正在查看 iperf 代码,试图找出它们的不同之处,但基本上,我找不到任何套接字或 udp 选项或它们为最大化 UDP 吞吐量所做的任何类似操作。

这是主函数的代码(MAXUDP定义为1470):

int main(int argc, char** argv) 
{
int sockfd;
struct sockaddr_in servaddr;
char sendline[MAXUDP];
int i;
int j;
const int tr_size = ( 200 * MB );
const int npackets = ( tr_size / MAXUDP );
const int neval = 2;
DWORD start;
DWORD end;
int optval;

WSADATA wsaData;
if(WSAStartup(MAKEWORD(2, 1), &wsaData) != 0 )
{
    printf( "Err: %d\n", WSAGetLastError() );
    exit(1);
}

bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
servaddr.sin_addr.s_addr = inet_addr("172.16.0.215");

sockfd = Socket(AF_INET, SOCK_DGRAM, 0);
Connect(sockfd, (const SA*) &servaddr, sizeof(servaddr));

optval = 208*KB;
Setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char*) &optval, sizeof optval);

prep_data(sendline, MAXUDP);

for ( i = 1; i <= neval; i++ )
{
    start = GetTickCount();
    for ( j = 0; j < npackets/neval; j++ )
        sendto(sockfd, sendline, MAXUDP, 0, NULL, NULL);
    end = GetTickCount() - start;

    printf("Time elapsed: %d sec.\n", end/1000);
    printf("Throughput: %d.%3d MB/s\n", (tr_size/neval)/end/1000, (tr_size/neval)/end - (tr_size/neval)/end/1000);
}
return 0;
}

所以,我的主要问题是如何以与 iperf 相同的方式最大化 UDP 吞吐量?

更新: 我切换到 Ubuntu PC。结果有所不同,但仍然有一些随机的事情发生。 我做的第一件事是设置 eth0 的 IP 地址 (ifconfig eth0 172.16.0.200 netmask 255.255.255.0) 和网关地址 (route add default gw 1​​72.16.0.1)。当我使用 iperf -c 172.16.0.215 -i 5 -t 25 -u -b 1000m 运行 iperf 时,我的速度约为 800 Mbits/sec。然而,以同样的方式运行几次 iperf 后,突然我的速度开始只有 15 Mbits/sec 左右,甚至更少。我发现我需要再次设置 IP、网络掩码和网关地址才能获得 800 Mbits/sec。另外,我的 UDP 应用程序的行为方式相同。在运行设置 IP 地址的命令后,我测量到 957 Mbits/sec(MAXUDP 设置为 1470)。但经过几次迭代后,速度减慢至 11 Mbits/sec 左右。然后我再次设置 IP 地址,该行为又重复出现。因此,正如 Kariem 在他的回答中所说,问题不在于代码本身,而在于某些操作系统、netif 配置相关的东西。但是,我必须在 Windows 上运行 UDP 应用程序,因此我需要弄清楚那里发生了什么。如果你们对 Windows 中可能发生的事情有任何想法,请立即告诉我。

最佳答案

您计算吞吐量的方式有误。您的大小以字节为单位设置,因此您以字节为单位计算吞吐量,而 iperf 以位为单位计算吞吐量。

改变

printf("Throughput: %d.%3d MB/s\n", (tr_size/neval)/end/1000, (tr_size/neval)/end - (tr_size/neval)/end/1000);

到此

printf("Throughput: %d.%3d MB/s\n", ((tr_size/neval)/end/1000)*8, (tr_size/neval)/end - ((tr_size/neval)/end/1000)*8);

我在我的机器上运行了您的代码版本,并且获得了 1GB 的吞吐量。在这里

#include <netinet/in.h>
#include <string.h>
#include <sys/time.h>
#include <cstdio>
#include <arpa/inet.h>
#include <fcntl.h>

#define MAXUDP 1470
#define SERV_PORT 5001
static inline long int getCurTimeInMs()
{
    struct timeval tp;
    gettimeofday(&tp, NULL);
    return tp.tv_sec * 1000 + tp.tv_usec / 1000;

}


int main(int argc, char** argv)
{
    int sockfd;
    struct sockaddr_in servaddr;
    char sendline[MAXUDP];
    int i;
    int j;
    const int tr_size = ( 10000 * 1024*1024 );
    const int npackets = ( tr_size / MAXUDP );
    const int neval = 2;

    int optval;

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERV_PORT);

        servaddr.sin_addr.s_addr = inet_addr("10.0.1.2");

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);


    connect(sockfd, (const sockaddr*) &servaddr, sizeof(servaddr));


    optval = 208*1024;
    setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char*) &optval, sizeof optval);
    long int start = 0, end = 0;
    for ( i = 1; i <= neval; i++ )
    {
        start = getCurTimeInMs();
        for ( j = 0; j < npackets/neval; j++ )
            sendto(sockfd, sendline, MAXUDP, 0, NULL, NULL);
        end = getCurTimeInMs() - start;

        printf("Time elapsed: %d sec.\n", end/1000);
        printf("Throughput: %d.%3d MB/s\n", (tr_size/neval)/end/1000 * 8, (tr_size/neval)/end - (tr_size/neval)/end/1000);

    }
    return 0;
}

关于c - 与 iperf UDP 性能相比,UDP 吞吐量较低,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43658097/

相关文章:

c++ - 如何最简洁地将变量初始化为0?

node.js - 如何扩展 nodejs 应用程序

linux - Bash 命令(netstat 等)显示数据包传输概览?

linux - Docker DNS 设置

c++ - 如何改进寻找二项式系数的递归算法

c - C的主要缺陷

c - scanf() 在 ENTER 后不起作用

cocoa - UNIX 域套接字和 Cocoa

java - 通过 java 套接字发送文件时出错

linux - Ifconfig 和 IPtables 配置