IP多播---C++实现

多播基础知识:

       普通IP通信是在一个发送者和一个接收者之间进行的,我们常把它称为点对点的通信,但对于有些应用,这种点对点的通信模式不能有效地满足实际应用的需求。例如:一个数字电话会议系统由多个会场组成,当在其中一个会场的参会人发言时,要求其它会场都能即时的得到此发言的内容,这是一个典型的一对多的通信应用,通常把这种一对多的通信称为多播通信。采用多播通信技术,不仅可以实现一个发送者和多个接收者之间进行通信的功能,而且可以有效减轻网络通信的负担,避免资源的无谓浪费。
 
  广播也是一种实现一对多数据通信的模式,但广播与多播在实现方式上有所不同。

      广播是将数据从一个工作站发出,局域网内的其他所有工作站都能收到它。这一特征适用于无连接协议,因为LAN上的所有机器都可获得并处理广播消息。使用广播消息的不利之处是每台机器都必须对该消息进行处理。

      多播通信则不同,数据从一个工作站发出后,如果在其它LAN上的机器上面运行的进程表示对这些数据“有兴趣”,多播数据才会制给它们。

     多播地址范围:224.0.0.0到239.255.255.255,但是很多是不能用的,例如:224.0.0.0是保留地址,具体的请自己查阅相关文档。。

    要实现接受到多播消息,那么你就必须加入多播组,那么这个组内的成员发送的多播消息,你才能接受的到。WSAJoinLeaf就是实现这个功能的。

实现:

接受者:

#include <iostream>
#include <string>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;

#define bufferSize 1024
void main()
{
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	wVersionRequested = MAKEWORD( 2, 2 );
	err = WSAStartup( wVersionRequested, &wsaData );
	if ( err != 0 ) {             
		return;
	}
	if ( LOBYTE( wsaData.wVersion ) != 2 ||
		HIBYTE( wsaData.wVersion ) != 2 ) {
			WSACleanup( );
			return; 
	}
	SOCKET socket;
	
	if((socket=WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0,WSA_FLAG_MULTIPOINT_C_LEAF|
		WSA_FLAG_MULTIPOINT_D_LEAF|WSA_FLAG_OVERLAPPED))==INVALID_SOCKET)
	{
		cout<<"socket failed with: "<<WSAGetLastError()<<endl;
		WSACleanup();
		return;
	}

	sockaddr_in localAddress;
	localAddress.sin_family=AF_INET;
	localAddress.sin_port=htons(2500);

	localAddress.sin_addr.S_un.S_addr=INADDR_ANY;

	int length=sizeof(localAddress);
	if(bind(socket,(sockaddr*)&localAddress,length)==SOCKET_ERROR)
	{
		cout<<" 绑定失败:"<<WSAGetLastError()<<endl;
		closesocket(socket);
		WSACleanup();
		return;
	}

	sockaddr_in remoteAddress;
	remoteAddress.sin_family=AF_INET;
	remoteAddress.sin_port=htons(2500);
	remoteAddress.sin_addr.S_un.S_addr=inet_addr("233.0.0.1");

	SOCKET socket_join;
	if((socket_join=WSAJoinLeaf(socket,(const sockaddr*)&remoteAddress,sizeof(remoteAddress),NULL,NULL,NULL,
		NULL,JL_BOTH))==SOCKET_ERROR)
	{
		cout<<"wsaJoinLeaf() failed: "<<WSAGetLastError()<<endl;
		closesocket(socket);
		WSACleanup();
		return;
	}

	char receiverBuf[bufferSize];
	sockaddr_in fromAddress;
	int len=sizeof(fromAddress);
	while (1)
	{
		int retCount;
		if((retCount=recvfrom(socket,receiverBuf,bufferSize,0,(sockaddr*)&fromAddress,&len))==SOCKET_ERROR)
		{
			cout<<"recvfrom failed with:"<<WSAGetLastError()<<endl;
			closesocket(socket_join);
			closesocket(socket);
			WSACleanup();
			return;
		}
		if (strcmp(receiverBuf,"quit")==0)
			break;
		else
		{
			receiverBuf[retCount]='\0';
			cout<<"data:"<<receiverBuf<<'\n'<<"from: "<<inet_ntoa(fromAddress.sin_addr)<<endl;
		}
	}
	closesocket(socket_join);
	closesocket(socket);
	WSACleanup();
	return;

}

加载winsock库版本等信息,初始化----->绑定到自己的IP端口------>加入多播组------>接受数据..


发送者:

#include <iostream>
#include <string>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;

#define bufferSize 1024
void main()
{
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	wVersionRequested = MAKEWORD( 2, 2 );
	err = WSAStartup( wVersionRequested, &wsaData );
	if ( err != 0 ) {             
		return;
	}
	if ( LOBYTE( wsaData.wVersion ) != 2 ||
		HIBYTE( wsaData.wVersion ) != 2 ) {
			WSACleanup( );
			return; 
	}
	SOCKET socket;

	if((socket=WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0,WSA_FLAG_MULTIPOINT_C_LEAF|
		WSA_FLAG_MULTIPOINT_D_LEAF|WSA_FLAG_OVERLAPPED))==INVALID_SOCKET)
	{
		cout<<"socket failed with: "<<WSAGetLastError()<<endl;
		WSACleanup();
		return;
	}

	sockaddr_in remoteAddress;
	remoteAddress.sin_family=AF_INET;
	remoteAddress.sin_port=htons(2500);
	remoteAddress.sin_addr.S_un.S_addr=inet_addr("233.0.0.1");

	SOCKET socket_join;
	if((socket_join=WSAJoinLeaf(socket,(const sockaddr*)&remoteAddress,sizeof(remoteAddress),NULL,NULL,NULL,
		NULL,JL_BOTH))==SOCKET_ERROR)
	{
		cout<<"wsaJoinLeaf() failed: "<<WSAGetLastError()<<endl;
		closesocket(socket);
		WSACleanup();
		return;
	}

	char sendBuffer[bufferSize];
	while(1)
	{
		cout<<"Send:  ";
		cin>>sendBuffer;
		if((sendto(socket,sendBuffer,strlen(sendBuffer),0,(sockaddr*)&remoteAddress,sizeof(remoteAddress)))==SOCKET_ERROR)
		{
			cout<<"Sendto failed with: "<<WSAGetLastError()<<endl;
			closesocket(socket_join);
			closesocket(socket);
			WSACleanup();
			return;
		}
		if(strcmp(sendBuffer,"quit")==0)
			break;
	}
	closesocket(socket);
	WSACleanup();
	return;

}

 

由于是参考着网上的例子写的,目前没有两台机器在旁边,所以不能测试能不能成功发送接受消息,每次启动第二个exe就直接消失。。大家自己找两台测试看看。。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值