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;
}

1937

被折叠的 条评论
为什么被折叠?



