天天看點

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就直接消失。。大家自己找兩台測試看看。。

繼續閱讀