【问题标题】:Sender/receiver behavior when receiver responds in network programming with broadcast接收方在网络编程中使用广播响应时的发送方/接收方行为
【发布时间】:2021-12-21 07:13:24
【问题描述】:

我正在学习网络编程中的广播(使用 C)。据我了解,发送者向局域网中的所有接收者(正在收听)发送消息。使用我的本地机器和虚拟机,我编写了一个小程序来查看它是如何工作的。

receiver.c 的代码(我将此代码放在本地机器上):

#include <stdio.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/unistd.h>

#define PORT 4242

int main() {
    int socket_fd, sender_size;
    struct sockaddr_in receiver, sender;
    char receive_buff[256], send_buff[256];

    socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (socket_fd < 0) {
        perror("failed to create socket");
        return -1;
    }

    int broadcast_yes = 1, reuse_yes = 1;
    if (setsockopt(socket_fd, SOL_SOCKET, SO_BROADCAST, (void*) &broadcast_yes, sizeof(broadcast_yes)) < 0) {
        perror("failed to set broadcast socket option");
        return -2;
    }

    if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, (void*) &reuse_yes, sizeof(reuse_yes)) < 0) {
        perror("failed to set reuse socket option");
        return -3;
    }

    memset(&receiver, 0, sizeof(receiver));
    receiver.sin_family = AF_INET;
    receiver.sin_port = htons(PORT);
    receiver.sin_addr.s_addr = INADDR_ANY;

    if (bind(socket_fd, (struct sockaddr*) &receiver, sizeof(receiver)) < 0) {
        perror("failed to bind");
        return -4;
    }

    printf("Listening...\n");
    memset(receive_buff, 0, sizeof(receive_buff));
    sender_size = sizeof(sender);
    if (recvfrom(socket_fd, (void*)receive_buff, sizeof(receive_buff), 0, (struct sockaddr*) &sender, &sender_size) < 0) {
        perror("failed to receive broadcast message");
        return -5;
    }

    printf("%s\n", receive_buff);

    strcpy(send_buff, "got your message");
    if (sendto(socket_fd, (void*)send_buff, sizeof(send_buff), 0, (struct sockaddr*) &sender, sizeof(sender)) < 0) {
        perror("failed to send confirmation message");
        return -6;
    }

    close(socket_fd);

    return 0;
}

sender.c 的代码(我将此代码放在我的虚拟机上):

#include <stdio.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>

#define PORT 4242

int main() {
    int socket_fd;
    struct sockaddr_in receiver;
    char send_buff[256], receive_buff[256];
    socklen_t receiver_size;

    socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (socket_fd < 0) {
        perror("failed to create socket");
        return -1;
    }

    int broadcast_yes = 1;
    if (setsockopt(socket_fd, SOL_SOCKET, SO_BROADCAST, (void*) &broadcast_yes, sizeof(broadcast_yes)) < 0) {
        perror("failed to set broadcast socket option");
        return -2;
    }

    memset(&receiver, 0, sizeof(receiver));
    receiver.sin_family = AF_INET;
    receiver.sin_port = htons(PORT);
    receiver.sin_addr.s_addr = inet_addr("192.168.1.255");

    strcpy(send_buff, "i'm sending a broadcast message");
    if (sendto(socket_fd, (void*)send_buff, strlen(send_buff) + 1, 0, (struct sockaddr*) &receiver, sizeof(receiver)) < 0) {
        perror("failed to send broadcast message");
        return -3;
    }

    memset(receive_buff, 0, sizeof(receive_buff));
    receiver_size = sizeof(receiver);
    if (recvfrom(socket_fd, (void*)receive_buff, sizeof(receive_buff), 0, (struct sockaddr*) &receiver, &receiver_size) < 0) {
        perror("failed to receive confirmation message");
        return -4;
    }

    printf("%s\n", receive_buff);

    close(socket_fd);

    return 0;
}

如您所见,没有什么花哨的。 sender 将消息i'm sending a broadcast message 作为广播消息发送(因为我将255 放在IPv4 地址的末尾,并且我还在套接字中设置了SO_BROADCAST 选项)。反过来,receiver 等待并接收此消息。它还在套接字中启用了SO_BROADCAST 选项。之后发生的事情让我感到困惑。如上所示,receiver 收到消息后,会向发送者发送一条确认消息got your message

但是如果一个发送者将消息发送给局域网中的所有接收者(监听者)并且局域网中有多个接收者,这将如何工作?多个接收者中的每一个不会将got your message 确认消息发送给发送者吗?因此,就像多台机器在receiver.c 中有该代码,并且当代码调用函数recvfrom() 时,每台机器都会在变量struct sockaddr_in sender 中获取sender 的地址信息。然后,所有这些机器都会将该消息got your message 发送到sender。但是发件人只有一个recvfrom() 函数调用,所以它只会收到到达它的第一条消息。其他接收者的确认消息将丢失。或者至少这就是我认为将会发生的事情。我该如何解决这个问题并获得所有确认消息?同样,这个问题仅适用于我对上面所说的情况的理解是正确的,我不知道是不是这样,所以我还要问你我认为发件人只会收到一条确认消息是否正确。

【问题讨论】:

    标签: c sockets network-programming


    【解决方案1】:

    你的理解是正确的。

    如果您广播一条消息并且接收者的多个实例得到它,每个都会将响应发送回发送者。

    这意味着发送者需要循环调用recvfrom来接收多条消息。但与此同时,您不希望发件人永远等待,因为您不知道会收到多少回复。

    处理这个问题的最简单方法是使用select 函数来检查是否有要读取的数据。你可以给这个函数一个超时时间,这样你就可以控制它等待的时间。如果它返回一个正值,则有数据要读取,您可以调用recvfrom 来读取响应,然后再次调用select 以等待更多。如果返回 0,则等待响应超时。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-15
      • 1970-01-01
      • 1970-01-01
      • 2021-12-21
      • 1970-01-01
      • 1970-01-01
      • 2012-08-11
      • 2013-08-22
      相关资源
      最近更新 更多