windows下UDP组播

最近研究下UDP组播,首先上网看看各种组播的含义,以下是总结的:

    多播,也称为“组播”,将网络中同一业务类型主机进行了逻辑上的分组,进行数据收发的时候其数据仅仅在同一分组中进行,其他的主机没有加入此分组不能收发对应的数据。

    在广域网上广播的时候,其中的交换机和路由器只向需要获取数据的主机复制并转发数据。主机可以向路由器请求加入或退出某个组,网络中的路由器和交换机有选择地复制并传输数据,将数据仅仅传输给组内的主机。多播的这种功能,可以一次将数据发送到多个主机,又能保证不影响其他不需要(未加入组)的主机的其他通 信。

多播的地址是特定的,D类地址用于多播。D类IP地址就是多播IP地址,即224.0.0.0至239.255.255.255之间的IP地址,并被划分为局部连接多播地址、预留多播地址和管理权限多播地址3类:

  1、局部多播地址:在224.0.0.0~224.0.0.255之间,这是为路由协议和其他用途保留的地址,路由器并不转发属于此范围的IP包。

  2、预留多播地址:在224.0.1.0~238.255.255.255之间,可用于全球范围(如Internet)或网络协议。

  3、管理权限多播地址:在239.0.0.0~239.255.255.255之间,可供组织内部使用,类似于私有IP地址,不能用于Internet,可限制多播范围。

  多播的程序设计使用setsockopt()函数和getsockopt()函数来实现,组播的选项是IP层的,其选项值和含义参见下表。

                         

getsockopt()/setsockopt()的选项

含 义

IP_MULTICAST_TTL

设置多播组数据的TTL值

IP_ADD_MEMBERSHIP

在指定接口上加入组播组

IP_DROP_MEMBERSHIP

退出组播组

IP_MULTICAST_IF

获取默认接口或设置接口

IP_MULTICAST_LOOP

禁止组播数据回送

下面是写的实例代码:

client代码

#include <stdio.h>  
#include <winsock2.h>  
#include <ws2tcpip.h>  
#pragma comment(lib, "ws2_32.lib")

int main()
{
	int iRet = 0;
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);

	SOCKET sock = socket(AF_INET,SOCK_DGRAM,0);

	int iFlag = 0;	// 0-同一台主机 1-夸主机
	iRet = setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&iFlag, sizeof(iFlag));
	if(iRet != 0){
		printf("setsockopt fail:%d", WSAGetLastError());
		return -1;
	}

	sockaddr_in addr;
	addr.sin_addr.S_un.S_addr = inet_addr("234.2.2.2");
	addr.sin_family = AF_INET;
	addr.sin_port = htons(9411);
	
	char strSend[1024] = {0};
	static int iIdx = 0;
	while(1)  
	{     
		sprintf_s(strSend, "udp send group data:%d", iIdx++);
		iRet = sendto(sock, strSend, strlen(strSend) + 1, 0, (sockaddr*)&addr, sizeof(sockaddr));
		if(iRet <= 0){
			printf("send fail:%d", WSAGetLastError());
		}else{
			printf("send data:%s\n", strSend);
		}
		Sleep(500); 
	}  

	closesocket(sock);
	WSACleanup();

	return 0;
}

server代码:

#include <stdio.h>  
#include <winsock2.h>  
#include <ws2tcpip.h>  
#pragma comment(lib, "ws2_32.lib")

int main()
{
	int iRet = 0;
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);

	SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);

	sockaddr_in addr;
	addr.sin_family = AF_INET;
	//addr.sin_addr.S_un.S_addr = INADDR_ANY;
	addr.sin_addr.S_un.S_addr = inet_addr("192.168.0.104");
	addr.sin_port = htons(9411);

 	bool bOptval = true;
 	iRet = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&bOptval, sizeof(bOptval));
 	if(iRet != 0){
 		printf("setsockopt fail:%d", WSAGetLastError());
 		return -1;
 	}

	iRet = bind(sock, (sockaddr*)&addr, sizeof(addr));
	if(iRet != 0){
		printf("bind fail:%d", WSAGetLastError());
		return -1;
	}
	printf("socket:%d bind success\n", sock);

	// 加入组播  
	ip_mreq multiCast;
	//multiCast.imr_interface.S_un.S_addr = INADDR_ANY;
	multiCast.imr_interface.S_un.S_addr = inet_addr("192.168.0.104");
	multiCast.imr_multiaddr.S_un.S_addr = inet_addr("234.2.2.2");
	iRet = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&multiCast, sizeof(multiCast));
	if(iRet != 0){
		printf("setsockopt fail:%d", WSAGetLastError());
		return -1;
	}

	printf("udp group start\n");

	int len = sizeof(sockaddr);
	char strRecv[1024] = {0};
	while(true)  
	{     
		memset(strRecv, 0, sizeof(strRecv));
		iRet = recvfrom(sock, strRecv, sizeof(strRecv) - 1, 0, (sockaddr*)&addr, &len);
		if(iRet <= 0){
			printf("recvfrom fail:%d", WSAGetLastError());
			return -1;
		}
		printf("recv data:%s\n", strRecv);
	}  

	closesocket(sock);
	WSACleanup();

	return 0;
}

 

 

©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页