Windows C++ 编程:UDP组播

Windows C++ 编程:UDP组播

UDP的三种信息传递方式:

  • 单播(UniCast):用于两个主机之间单对单的通信;
  • 广播(BroadCast):用于一个主机对整个局域网上所有主机上的数据通信;
  • 组播/多播(MultiCast):允许一台或多台主机发送数据包到多台主机;

组播报文的目的地址需使用D类IP地址,范围从 224.0.0.0到239.255.255.255。本文将分享在Windows环境下使用C++编写的UDP组播示例,不同的操作系统环境使用的头文件及函数略有不同。Windows环境下函数详解可在微软网站中查看:winsock.h API

UDP发送端《sender.cpp》示例代码如下:

//编译命令:g++ .\sender.cpp -lws2_32 -o sender
#include <iostream>
#include <Winsock2.h>
using namespace std;
#pragma comment(lib, "Ws2_32.lib")

//向组播地址为224.0.0.88的组发送信息
int main() {
    //通过进程启动 Winsock DLL 的使用(启动之后,这个库里的函数/功能才能使用)
    WSADATA wsaData;
    (void)WSAStartup(MAKEWORD(2,2), &wsaData);
   //创建套接字描述符
    int socked=socket(AF_INET,SOCK_DGRAM,0);
    //创建本地地址结构体并对本机ip、使用的端口号进行赋值
    struct sockaddr_in local_addr;
    memset(&local_addr,0,sizeof(local_addr));
    local_addr.sin_family = AF_INET;
    local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    local_addr.sin_port = htons(0x3000);
    //套接字绑定本地地址(使用设定的端口向外发送udp报文)
    int ret = bind(socked, (struct sockaddr*)&local_addr, sizeof(local_addr));
    if(ret == -1)
    {
        perror("bind failed !");
        return 3;
    }
    //初始化组地址信息
    struct sockaddr_in remote_addr;
    memset(&remote_addr,0,sizeof(remote_addr));
    remote_addr.sin_family=AF_INET;
    remote_addr.sin_addr.s_addr=inet_addr("224.0.0.88");
    remote_addr.sin_port=htons(8888);
    //调用sendto函数向组中发送报文
    char buf[1024]="This is a group udp";
    int length=0;
    length=sendto(socked,buf,strlen(buf),0,(struct sockaddr *)&remote_addr,sizeof(remote_addr));
    printf("Send Message: %s\n",buf);

    return 0;
}

UDP接收端《recv.cpp》示例代码如下:

//编译命令:g++ .\recv.cpp -lws2_32 -o recv
#include <iostream>
#include <Winsock2.h>
#include <ws2tcpip.h> 
using namespace std;
#pragma comment(lib, "Ws2_32.lib")

// 接收组播地址为224.0.0.88  的信息
int main(int argc,char *argv[]){
    //通过进程启动 Winsock DLL 的使用(启动之后,这个库里的函数/功能才能使用)
    WSADATA wsaData;
    (void)WSAStartup(MAKEWORD(2,2), &wsaData);
    //创建套接字描述符
    SOCKET socked=socket(AF_INET,SOCK_DGRAM,0);
    //创建本地地址结构体并对本机ip、使用的端口号进行赋值
    struct sockaddr_in local_addr;
    memset(&local_addr,0,sizeof(local_addr));
    local_addr.sin_family = AF_INET;
    local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    local_addr.sin_port = htons(8888);
    //套接字绑定本地地址
    int ret = bind(socked, (struct sockaddr*)&local_addr, sizeof(local_addr));
    if(ret == -1)
    {
        perror("bind failed !");
        return 3;
    }
    //组地址结构体创建
    struct ip_mreq mreq;
    mreq.imr_multiaddr.s_addr = inet_addr("224.0.0.88");
    mreq.imr_interface.s_addr = htonl(INADDR_ANY);

    /*
     *
     *  int setsockopt(int sockfd, int level, int optname,
                      const void *optval, socklen_t optlen);
     * param:
     *      optname
     *          * IP_MULTICAST_LOOP 支持多播数据回送
     *          * IP_ADD_MEMBERSHIP 加入多播组
     *          * IP_DROP_MEMBERSHIP 离开多播组
     *      optval
     *          * IP_MULTICAST_LOOP 选项对应传入 unsigned int 来确认是否支持多播数据回送
     *          * IP_ADD_MEMBERSHIP 传入 ip_mreq
     *          * IP_DROP_MEMBERSHIP 传入 ip_mreq
     *
     * */
    //套接字加入组播
    ret=setsockopt(socked,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char*)&mreq,sizeof(mreq));

    //使用recvfrom函数从组中接收udp报文
    char buf[1024];
    int length=0;
    struct sockaddr_in sender;
    socklen_t sender_len=sizeof(sender);
    while (true){
        memset(buf, 0, sizeof(buf));
        length=recvfrom(socked, buf, sizeof(buf), 0, (struct sockaddr*)&sender,&sender_len);
        buf[length]='\0';
        printf("%s %d : %s\n",inet_ntoa(sender.sin_addr),ntohs(sender.sin_port),buf);
    }
    //套接字离开组播
    setsockopt(socked, IPPROTO_IP, IP_DROP_MEMBERSHIP,(char*)&mreq, sizeof(mreq));
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值