UDP多播:一对多数据收发

多播

1.先来回顾一下,UDP广播。一个服务器进行广播,那么同一网络的所有主机都会收到信息。那么这个时候,有可能并不是所有主机都需要收到广播数据信息,只是一部分主机需要收到广播数据信息而已。
2.UDP通信中的多播。多播是向特定组中的所有的主机发送数据的方法,多播也称为组播。举个容易理解的例子:我们在qq/wechat 中有10个联系好友,拉了其中6个联系好友建立了一个群。那么其他4个好友肯定收不到群里的消息。
3.多播数据传输的特点:
3.1 多播是向特定组中的所有主机传输数据的方法,多播也称之为组播。
3.2 多播数据传输的特点。
a.多播发送者针对特定的多播组,只发送1次数据,组内主机均可收到数据
b.主机加入特定组,即可接收改组中的多播数据
c.多播组可在IP地址范围内任意增加

关键问题:如何收发多播数据?

1.多播组是一个D类地址(224.0.0.0 ~ 239.255.255.255)
2.加入多播组,可以理解为UDP网络程序进行的申请(也就是申请D类地址)
2.1 如:申请接收发往 239.234.111.222 的多播数据
2.2 即:设置熟悉(IPPROTO_IP,IP_ADD_MEMBERSHIP)
3.发送多播数据的方式,与发送普通UDP数据的方式相同
3.1 预备操作:设置熟悉,如:(IPPROTO_IP,IP_MULTICAST_TTL)

注意事项

1.加入同一个多播组的主机不一定在同一个网络中
2.因此,必须设置多播数据的最多转发次数(TTL)
3.TTL (即:Time to Live) 是决定数据传递距离的注意因素
4.TTL 用整数表示,并且每经过1个路由器就减少1
5.当TTL变为0时候,数据无法继续传递,只能销毁

多播程序设计:发送端

1.IP_MULTICAST_TTL :用于设置多播数据的 “最远传播距离”,默认:1
2.IP_MULTICAST_IF :用于设置多播数据从哪一个网络接口(网卡)发送出去:默认:0.0.0.0 (也就是让操作系统决定使用哪一个网口)
3.IP_MULTICAST_LOOP :用于设置多播数据是否发送会本机,默认:1

发送端:

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

int main()
{
    int server = 0;
    struct sockaddr_in saddr = {0};
    int client = 0;
    struct sockaddr_in remote = {0};
    socklen_t asize = 0;
    int len = 0;
    char buf[32] = "Software";
    int r = 0;
    //int brd = 1;

    server = socket(PF_INET, SOCK_DGRAM, 0);

    if( server == -1 )
    {
        printf("server socket error\n");
        return -1;
    }

    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = htonl(INADDR_ANY); // 本机地址
    saddr.sin_port = htons(8888);

    if( bind(server, (struct sockaddr*)&saddr, sizeof(saddr)) == -1 )
    {
        printf("udp server bind error\n");
        return -1;
    }

    printf("udp server start success\n");

    remote.sin_family = AF_INET;
    remote.sin_addr.s_addr = inet_addr("224.1.1.168"); //设置一个多播地址
    remote.sin_port = htons(9000);

    // brd = 0;

    //setsockopt(server, SOL_SOCKET, SO_BROADCAST, &brd, sizeof(brd));

    while( 1 )
    {
        len = sizeof(remote);

        r = strlen(buf);
        
        sendto(server, buf, r, 0, (struct sockaddr*)&remote, len);

        sleep(1);
    }
    
    close(server);

    return 0;
}

接收端:

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

int main()
{
    int sock = 0;
    struct sockaddr_in addr = {0};
    struct sockaddr_in remote = {0};
    int len = 0;
    char buf[128] = {0};
    char input[32] = {0};
    int r = 0;

    //多播
    struct ip_mreq group={0};

    sock = socket(PF_INET, SOCK_DGRAM, 0);

    if( sock == -1 )
    {
        printf("socket error\n");
        return -1;
    }

    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_port = htons(9000);

    if( bind(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1 )
    {
        printf("udp bind error\n");
        return -1;
    }

    //remote.sin_family = AF_INET;
    //remote.sin_addr.s_addr = inet_addr("127.0.0.1");
    //remote.sin_port = htons(8888);

    group.imr_multiaddr.s_addr=inet_addr("224.1.1.168");
    group.imr_interface.s_addr=htonl(INADDR_ANY); //local host
    //这里INADDR_ANY 为0.0.0.0 通过看ipconfig/ifconfig 可以看到有多个
    //网络ip地址,这个时候让操作系统选择哪一个端口进行多播数据收发。
    //在实际的工程中需要明确指定需要哪一个网络地址进行多播数据收发,
    //不能完全依赖操作系统,否者有时候能够收到数据,有时候收不到数据。
    
    setsockopt(sock,IPPROTO_IP,IP_ADD_MEMBERSHIP,&group,sizeof(group));

    while( 1 )
    {
        len=sizeof(remote);

        r = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr*)&remote, &len);

        if( r > 0 )
        {
            buf[r] = 0;

            printf("Receive: %s\n", buf);
        }
        else
        {
            break;
        }
    }

    close(sock);

    return 0;
}
运行结果:
发送端:
wj@ubuntu:~/DTSocket/17$ gcc mul_tx_server.c -o mul_tx_server.out
wj@ubuntu:~/DTSocket/17$ ./mul_tx_server.out 
udp server start success

接收端:
wj@ubuntu:~/DTSocket/17$ gcc mul_rx_client.c -o mul_rx_client.out
wj@ubuntu:~/DTSocket/17$ ./mul_rx_client.out 
Receive: Software
Receive: Software
Receive: Software

demo2:
//
//

小结:
1.单播:一对一数据发送,即:指定目标主机发送数据
2.广播:
2.1 本地广播:本地局域网广播数据,所有主机均可接收数据
2.2 直接广播:直接网络广播数据,目标网络中的主机均可接收数据。
3.多播(组播) :向指定的多播地址发送数据,“订阅”该地址的主机均可接收数据。

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在UE4中,可以使用UDP(User Datagram Protocol)多播来实现网络通信。UDP多播是一种一对多的通信方式,允许一个主机向多个目标主机发送数据。 下面是一个简单的示例,演示如何使用UE4C++来实现UDP多播收发消息。 首先,在UE4中创建一个C++项目,并在项目中添加以下代码: ```cpp #include "UdpSocket.h" #include "UdpSocketReceiver.h" void AUdpMulticastTest::BeginPlay() { Super::BeginPlay(); // 创建UDP套接字 FUdpSocketReceiver* SocketReceiver = new FUdpSocketReceiver(Socket, FTimespan::FromMilliseconds(100), TEXT("UDPReceiverThread")); if (SocketReceiver != nullptr) { // 绑定UDP套接字 FIPv4Endpoint Endpoint(FIPv4Address::Any, 12345); Socket->Bind(Endpoint); // 开始接收消息 SocketReceiver->Start(); } } void AUdpMulticastTest::EndPlay(const EEndPlayReason::Type EndPlayReason) { // 关闭UDP套接字 if (Socket != nullptr) { Socket->Close(); ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(Socket); Socket = nullptr; } Super::EndPlay(EndPlayReason); } void AUdpMulticastTest::HandleReceivedData(const FArrayReaderPtr& Data, const FIPv4Endpoint& SenderEndpoint) { FString Message; *Data << Message; UE_LOG(LogTemp, Log, TEXT("Received message: %s"), *Message); } void FUdpSocketReceiver::Tick(float DeltaTime) { Super::Tick(DeltaTime); if (!Socket) return; TSharedPtr<FInternetAddr> SenderAddress = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr(); uint32 Size; while (Socket->HasPendingData(Size)) { TArray<uint8> ReceivedData; ReceivedData.SetNumUninitialized(FMath::Min(Size, 65507u)); int32 Read = 0; Socket->RecvFrom(ReceivedData.GetData(), ReceivedData.Num(), Read, *SenderAddress); if (Read > 0) { FArrayReaderPtr Reader = MakeShareable(new FArrayReader(ReceivedData)); Reader->SetNum(Read); HandleReceivedData(Reader, FIPv4Endpoint(SenderAddress)); } } } ``` 在这段代码中,我们首先创建了一个UDP套接字,并将其绑定到本地IP地址和端口号12345上。然后,我们使用FUdpSocketReceiver类来接收UDP消息。当我们接收到消息时,会将消息内容打印到UE4的日志中。 接下来,我们可以使用以下代码来发送UDP消息: ```cpp void AUdpMulticastTest::SendUdpMessage(const FString& Message, const FString& MulticastAddress, int32 Port) { TSharedRef<FInternetAddr> Address = CreateInternetAddr(); Address->SetIp(*MulticastAddress, false); Address->SetPort(Port); const TCHAR* MessageData = *Message; int32 Size = FCString::Strlen(MessageData); int32 Sent = 0; Socket->SendTo((const uint8*)TCHAR_TO_UTF8(MessageData), Size, Sent, *Address); } ``` 在这段代码中,我们首先创建了一个FInternetAddr实例,并将其设置为多播地址和端口号。然后,我们使用UDP套接字的SendTo方法将消息发送到指定的地址和端口号。 通过以上代码,我们就可以在UE4C++中实现UDP多播收发消息了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

repinkply

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值