C 中的 UDP 套接字 - recvfrom() 似乎没有按预期从套接字读取数据

问题描述 投票:0回答:1

我为此创建了一个帐户,因为我在这里束手无策: 目标是让服务器接收并读取消息“Hello from client”中的 2 个字节 - 使用 recvfrom() 一次读取 1 个字节。 这是行不通的 - 第一个 recvfrom() 使程序无限期地休眠(我没有故意设置超时)。根据记录,我使用的是带有 Oracle VM VirtualBox 的 Linux (Ubuntu) 虚拟机,而且我对 C 编程相当陌生。 下面粘贴了 udp_server.c 和 udp_client.c 代码,希望有任何见解。

udp_server.c:

int main(void) {
    /* Socket */
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock == -1) {
        perror("socket(2)");
        return 1;
    }

    /* Set socket option SO_REUSEADDR */
    int opt = 1;
    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
        perror("setsockopt(2)");
        close(sock);
        return 1;
    }

    /* server sockaddr_in struct */
    struct sockaddr_in server;
    memset(&server, 0, sizeof(server));
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_family = AF_INET;
    server.sin_port = htons(5061);

    /* Bind */
    if (bind(sock, (struct sockaddr*)&server, sizeof(server)) < 0) {
        perror("bind(2)");
        close(sock);
        return 1;
    }

    /* client sockaddr_in struct (for recvfrom()) */
    struct sockaddr_in client;
    socklen_t client_len = sizeof(client);
    memset(&client, 0, sizeof(client));

    /* Receive data from socket */
    fprintf(stdout, "Listening on port %d...\n", 5061);
    char buffer[1024] = { 0 };
    int bytes_received = recvfrom(sock, buffer, 1, 0, (struct sockaddr*)&client, &client_len);
// PROGRAM FREEZES HERE ^^^
    if (bytes_received < 0) {
        printf("bytes_received %d, errno %d", bytes_received, errno);
        perror("recvfrom");
        close(sock);
        return 1;
    }
    printf("SUCCESS(1) bytes_received %d", bytes_received);
    bytes_received = recvfrom(sock, buffer, 1, 0, (struct sockaddr*)&client, &client_len);
    if (bytes_received < 0) {
        printf("bytes_received %d, errno %d", bytes_received, errno);
        perror("recvfrom");
        close(sock);
        return 1;
    }
    printf("SUCCESS(2) bytes_received %d", bytes_received);

    /* Shutdown */
    shutdown(sock, SHUT_RDWR);
    close(sock);
    return 0;
}

udp_client.c:

int main(void) {
    /* Socket */
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock == -1) { // In case socket creation failed.
        fprintf(stdout, "ERROR: Socket creation failed.\n");
        return -1;
    }

    /* Server sockaddr_in struct (for sendto()) */
    struct sockaddr_in server;
    memset(&server, 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(5061);
    if (inet_pton(AF_INET, "127.0.0.1", &server.sin_addr) <= 0) {
        perror("inet_pton(3)");
        close(sock);
        return 1;
    }

    /* Send data to socket */
    char* message = "Hello from client";
    int bytes_sent = sendto(sock, message, strlen(message), 0, (struct sockaddr*)&server, sizeof(server));
    if (bytes_sent <= 0) {
        perror("sendto(2)");
        close(sock);
        return 1;
    }
    fprintf(stdout, "Sent %d bytes to %s:%d - %s\n",
        bytes_sent, inet_ntoa(server.sin_addr), ntohs(server.sin_port), message);
    usleep(75000);

    /* Shutdown */
    shutdown(sock, SHUT_RDWR);
    close(sock);
    return 0;
}
c sockets udp localserver
1个回答
0
投票

udp_client
程序向
udp_server
程序发送一个17字节的数据报,该程序需要两个各1字节的数据报。第一个数据报中多余的 16 个字节将被丢弃。

如果

udp_client
程序运行两次,那么两个17字节的数据报将被发送到
udp_server
程序。每个接收到的数据报中多余的 16 个字节将被丢弃,因此
udp_server
会将以下内容写入标准输出流,作为读取两个数据报的结果:

Listening on port 5061...
SUCCESS(1) bytes_received 1SUCCESS(2) bytes_received 1

注意:输出后没有换行符。 “udp_server.c”中唯一在格式字符串末尾包含换行符的

printf
调用是打印
Listening on port 5061...
消息的调用。如果标准输出流是行缓冲,则其他
printf
调用的输出将保持缓冲状态,直到程序退出,此时缓冲的内容将输出到终端。 Unix 中常见的 Unix 约定是将标准输入、标准输出和标准错误流初始化为“行缓冲”,除非已知这些流未连接到交互式设备(即终端),在这种情况下,标准输入和标准输出流可以完全缓冲

© www.soinside.com 2019 - 2024. All rights reserved.