【问题标题】:How to simply send UDP data in C?如何在 C 中简单地发送 UDP 数据?
【发布时间】:2017-11-24 10:38:23
【问题描述】:

我正在为 UDP 套接字而苦苦挣扎。我想对两台机器之间交换某种类型数据的时间进行基准测试。

我很快用 C 语言编写了这个项目 https://github.com/nowox/udp-test,我有一个简单的客户端:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <netdb.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <time.h>
#include <errno.h>

#define PORT (3000)

#define SUBIMAGES (1000)
#define FRAMES_PER_SUBIMAGES (23)
#define UDP_FRAME (1442)

#define SERVERADDRESS "127.0.0.1" // 138.131.156.36"

#define BUFFER_SIZE (SUBIMAGES * FRAMES_PER_SUBIMAGES * UDP_FRAME)


char buffer[BUFFER_SIZE];

/**
 * Populate the buffer with random data.
 */
void build(uint8_t* buffer, size_t length)
{
    for (size_t i = 0; i < length; i++)
    {
        buffer[i] = (rand() % 255) + 1;
    }
}

int main(int argc, char **argv)
{
    struct timespec start, end;
    int sockfd;
    struct sockaddr_in server;

    printf("Build Data...\n");
    build(buffer, sizeof(buffer));

    printf("Configure socket...\n");
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        fprintf(stderr, "Error opening socket");
        return EXIT_FAILURE;
    }

    bzero((char*)&server, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = inet_addr(SERVERADDRESS);
    server.sin_port = htons(PORT);

    printf("Send UDP data...\n");
    clock_gettime(CLOCK_MONOTONIC_RAW, &start);
    for (size_t i = 0; i < BUFFER_SIZE; i += UDP_FRAME)
    {
        if (sendto(sockfd, &buffer[i], UDP_FRAME, 0,
                   (const struct sockaddr*)&server, sizeof(server)) < 0)
        {
            fprintf(stderr, "Error in sendto()\n");
            return EXIT_FAILURE;
        }
    }
    clock_gettime(CLOCK_MONOTONIC_RAW, &end);
    uint64_t delta_us = (end.tv_sec - start.tv_sec) * 1000000 +
                        (end.tv_nsec - start.tv_nsec) / 1000;

    printf("Time to send %d subimages: %f[s]\n", SUBIMAGES, delta_us / 1e6f);
    printf("Finished...\n");

    return EXIT_SUCCESS;
}

我希望在 Wireshark 中看到 UDP 数据帧,但我似乎什么也没看到。

最初的问题:为什么我的套接字没有发送任何东西?

我发现这是因为 WSL(适用于 Linux 的 Windows 子系统)。所以我搬到了 Ubuntu

第二个问题:为什么我的服务器收不到任何东西?

【问题讨论】:

  • 我看到你的数据包带有 tcpdump (sudo tcpdump -i lo -p udp -v)。你在听正确的网络接口吗?
  • 对,tcpdump 看起来没问题...所以我的服务器还有另一个问题,它没有收到我的数据包:(
  • 我花了一整天的时间试图诊断这样的 UDP 问题,却发现 IT 将网络配置为阻止我正在测试的两台计算机之间的 UDP 流量。您是否可能需要调整防火墙配置?
  • lockcmpexchg:他正在测试环回。
  • 请不要更改您的问题,使所有 cmets 和答案无效。如果您有第二个问题,请在单独的问题中提出。

标签: c sockets udp


【解决方案1】:

您将客户端绑定到与服务器相同的端口。这是无效的。你不需要绑定你的客户端。

在客户端注释掉你的绑定调用,数据包将从随机选择的端口发送到服务器。您的服务器会收到它们,但您的服务器中存在退出条件的另一个错误,所以当您收到帧时添加一些打印输出以查看它实际发生的情况。

【讨论】:

  • 我从客户端删除了绑定。我意识到这是一个错误,但仍然如此。服务器没有收到任何东西。
  • 在服务器中的 recv 之前或之后添加打印输出。对我来说,它确实收到了数据包(但你的版本什么也没打印出来,因为循环永远不会结束)。
【解决方案2】:

wsl 没有打开 Windows 防火墙并且数据包丢失。 用mingw编译(添加ws2_32)就可以了

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-07
    • 1970-01-01
    • 2022-01-19
    • 2019-03-20
    • 1970-01-01
    • 2019-01-04
    相关资源
    最近更新 更多