Socketネットワークプログラミングのマルチキャスト実現(C++,Rust)


実際のプロジェクトでは、マルチキャストがよく使われます。コードの例は以下の通りです。
一、C++実現(Windows)
サービスのソースコードのサービスは、マルチキャストグループに追加する必要があります。
#include "stdafx.h"
#include
#include	//ip_mreq   
#include
using namespace std;
#pragma comment(lib,"ws2_32.lib")

int _tmain(int argc, _TCHAR* argv[])
{
	WSADATA WSAData;
	WORD sockVersion=MAKEWORD(2,2);
	if(WSAStartup(sockVersion,&WSAData)!=0)
		return 0;

	SOCKET serSocket = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);	//     socket
	if(INVALID_SOCKET==serSocket)
	{
		cout<<"socket error!";
		return 0;
	}

	//      、         
	sockaddr_in serAddr;
	serAddr.sin_family=AF_INET;
	serAddr.sin_port=htons(8888);
	serAddr.sin_addr.S_un.S_addr=INADDR_ANY;

	if(bind(serSocket,(sockaddr*)&serAddr,sizeof(serAddr))==SOCKET_ERROR)	 // socket     
	{
		cout<<"bind error";
		closesocket(serSocket);
		return 0;
	}

/* ip_mreq   
typedef struct ip_mreq {
    IN_ADDR imr_multiaddr;  // IP multicast address of group.
    IN_ADDR imr_interface;  // Local IP address of interface.
} IP_MREQ, *PIP_MREQ;
*/
	//     
	ip_mreq multiCast;
	multiCast.imr_interface.S_un.S_addr=INADDR_ANY;		//           IP  。
	multiCast.imr_multiaddr.S_un.S_addr=inet_addr("234.2.2.2");	//    IP  。
	setsockopt(serSocket,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char*)&multiCast,sizeof(multiCast));

	sockaddr_in clientAddr;
	int iAddrlen=sizeof(clientAddr);
	char buff[1024];	//           
	while(true)
	{
		memset(buff,0,1024);	//        
		//       
		int len=recvfrom(serSocket,buff,1024,0,(sockaddr*)&clientAddr,&iAddrlen);
		if(len>0)
		{
			cout<<"     :"<<inet_ntoa(clientAddr.sin_addr)<<endl;
			cout<<buff;

		//	sendto(serSocket,buff,1024,0,(sockaddr*)&clientAddr,iAddrlen);
		}
	}

	closesocket(serSocket);		//  socket 
	WSACleanup();

	return 0;
}

クライアントのソースのクライアントの変更は大きくありませんが、送信アドレスをマルチキャストアドレスに変更しました。
#include "stdafx.h"
#include
#include
using namespace std;
#pragma comment(lib,"ws2_32.lib")

int _tmain(int argc, _TCHAR* argv[])
{
	WSADATA WSAData;
	WORD sockVersion=MAKEWORD(2,2);
	if(WSAStartup(sockVersion,&WSAData)!=0)
		return 0;

	SOCKET clientSocket = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
	if(INVALID_SOCKET==clientSocket)
	{
		cout<<"socket error!";
		return 0;
	}

	sockaddr_in dstAddr;
	dstAddr.sin_family=AF_INET;
	dstAddr.sin_port=htons(8888);
	dstAddr.sin_addr.S_un.S_addr=inet_addr("234.2.2.2");

	const char* sendData="         。";

	sendto(clientSocket,sendData,strlen(sendData),0,(sockaddr*)&dstAddr,sizeof(dstAddr));

	closesocket(clientSocket);
	WSACleanup();

	return 0;
}
二、Rust実現
サービスコード:
use std::net::UdpSocket;
use std::net::Ipv4Addr;

fn main() {
    let mut socket = UdpSocket::bind("0.0.0.0:8888").unwrap();
    let mut buf = [0u8; 65535];
    let multi_addr = Ipv4Addr::new(234, 2, 2, 2);
    let inter = Ipv4Addr::new(0,0,0,0);
    socket.join_multicast_v4(&multi_addr,&inter);

    loop {
        let (amt, src) = socket.recv_from(&mut buf).unwrap();
        println!("received {} bytes from {:?}", amt, src);
    }
}

クライアントコード:
use std::net::UdpSocket;
use std::thread;

fn main() {
    let socket = UdpSocket::bind("0.0.0.0:9999").unwrap();
    let buf = [1u8; 15000];
    let mut count = 1473;
    socket.send_to(&buf[0..count], "234.2.2.2:8888").unwrap();

    thread::sleep_ms(1000);
}
三、マルチキャストに関する知識の補充
マルチキャストは、複数のホストが同時に1つのパケットの受信者となる場合、帯域幅とCPUに負担をかけることを考慮して、マルチキャストが最適な選択となるパケット伝送方式である。
マルチキャストは224.0.0.0-24.255.255.255のDタイプのアドレスを目的として、一つのソースホストが送信する目的地は上記の範囲のマルチキャストアドレスの新聞文です。ネットワークで他のホストがこのグループのレポートに興味があれば、このグループに参加することができます。他はこのグループのメンバーではないので、このグループのレポートは受け付けられません。
周知のDタイプIPアドレス:
D種アドレス
用途
224.0.0.1
ネット上のすべてのホストで
224.0.0.2
一つのサブネット上のすべてのルータ
224.0.0.4
すべてのDVMRPプロトコルのルータ
224.0.0.5
すべての開放最短経路優先(OSPF)ルータ
224.0.0.6
すべてのOSPF指定ルータ
224.0.0.9
すべてのRIPv 2ルータ
224.0.0.13
すべてのPIMプロトコルルータ
224.0.0.0-24.25
ローカル使用として保留し、管理とメンテナンスを行う。
239.0.0.0-39.255.255.255
残して管理して使う
最後に、個人のWeChat公式アカウントに注目してください。Let's go!