組播 IP_MULTICAST_LOOP迴環在Linux和Windows的差異

在TX2嵌入式開發板上(Ubuntu操作系統)編寫網絡組播發送接收程序,首先了解一下組播.

linux多播編程

linux多播編程步驟:

1>建立一個socket;

2>設置多播的參數,例如超時時間TTL,本地迴環許可LOOP等

3>加入多播組

的4>發送和接收數據

5>從多播組離開

多播程序設計使用setsockopt()函數和getsockopt()函數來實現,組播的選項是IP層的。

getsockopt()/setsockopt()的選項

含    義

IP_MULTICAST_TTL

設置多播組數據的TTL值

IP_ADD_MEMBERSHIP

在指定接口上加入組播組

IP_DROP_MEMBERSHIP

退出組播組

IP_MULTICAST_IF

獲取默認接口或設置接口

IP_MULTICAST_LOOP

禁止組播數據回送

1.選項IP_MULTICASE_TTL

選項IP_MULTICAST_TTL允許設置超時TTL,範圍爲0~255之間的任何值,例如:

unsigned char ttl=255;

setsockopt(s,IPPROTO_IP,IP_MULTICAST_TTL,&ttl,sizeof(ttl)); 

2.選項IP_MULTICAST_IF

選項IP_MULTICAST_IF用於設置組播的默認默認網絡接口,會從給定的網絡接口發送,另一個網絡接口會忽略此數據。例如:

struct in_addr addr;

setsockopt(s,IPPROTO_IP,IP_MULTICAST_IF,&addr,sizeof(addr));

參數addr是希望多播輸出接口的IP地址,使用INADDR_ANY地址回送到默認接口。

默認情況下,當本機發送組播數據到某個網絡接口時,在IP層,數據會回送到本地的迴環接口,選項IP_MULTICAST_LOOP用於控制數據是否回送到本地的迴環接口。例如:

unsigned char loop;

setsockopt(s,IPPROTO_IP,IP_MULTICAST_LOOP,&loop,sizeof(loop));參數loop設置爲0禁止回送,設置爲1允許回送。

 

3.選項IP_ADD_MEMBERSHIP和IP_DROP_MEMBERSHIP

加入或者退出一個多播組,通過選項IP_ADD_MEMBERSHIP和IP_DROP_MEMBER- SHIP,對一個結構struct ip_mreq類型的變量進行控制,struct ip_mreq原型如下:

struct ip_mreq          

    struct in_addr imn_multiaddr;      /*加入或者退出的廣播組IP地址*/ 

  struct in_addr imr_interface;      /*加入或者退出的網絡接口IP地址*/

};

 

選項IP_ADD_MEMBERSHIP用於加入某個多播組,之後就可以向這個多播組發送數據或者從多播組接收數據。此選項的值爲mreq結構,成員imn_multiaddr是需要加入的多播組IP地址,成員imr_interface是本機需要加入廣播組的網絡接口IP地址。例如:

struct ip_mreq mreq;

setsockopt(s,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq));

 

但是實際測試使用過程中,有時候發送方不需要接收自己發送出去的信息,所以使用IP_MULTICAST_LOOP,但是沒有工作,網絡上搜索發現很多人都遇到了相同的問題,衆說紛紜,有的說發送和接收使用相同的socket,發現下面這種說法更加靠譜.

Note  The Winsock version of the IP_MULTICAST_LOOP option is semantically different than the UNIX version of the IP_MULTICAST_LOOP option:

    In Winsock, the IP_MULTICAST_LOOP option applies only to the receive path.
    In the UNIX version, the IP_MULTICAST_LOOP option applies to the send path.

For example, applications ON and OFF (which are easier to track than X and Y) join the same group on the same interface; application ON sets the IP_MULTICAST_LOOP option on, application OFF sets the IP_MULTICAST_LOOP option off. If ON and OFF are Winsock applications, OFF can send to ON, but ON cannot sent to OFF. In contrast, if ON and OFF are UNIX applications, ON can send to OFF, but OFF cannot send to ON.

 

在windows平臺,  IP_MULTICAST_LOOP 應用到接收端.在接收端啓用IP_MULTICAST_LOOP. loop設置爲1,表示接收自身發送出去的數據,設置爲0表示不接收
在Linux平臺,  IP_MULTICAST_LOOP 應用到發送端.下面是實際的部分測試代碼

	int ret  = -1;
	int loop = 1;
	struct timeval timeout = {1,0};
	
	client_fd = socket(AF_INET, SOCK_DGRAM, 0);
	if(client_fd == -1)
	{
		Log_error("sock error \n");
		return -1;
	}
	/*��ʼ����ַ*/
	local_addr.sin_family = AF_INET;
	local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	local_addr.sin_port = htons(iPort);
	/*��socket*/
	ret=bind(client_fd,(struct sockaddr*)&local_addr,sizeof(local_addr));
	if(ret < 0)
	{
		close(client_fd);
		client_fd = -1;
		Log_error("bind error \n");
		return -2;
	}

	ret=setsockopt(client_fd,IPPROTO_IP,IP_MULTICAST_LOOP,&loop,sizeof(loop));
	if(ret < 0)
	{
		close(client_fd);
		client_fd = -1;
		Log_error("set sock error \n");
		return -3;
	}
	m_mreq.imr_multiaddr.s_addr = inet_addr(MCAST_ADDR);//�㲥��ַ
	m_mreq.imr_interface.s_addr = htonl(INADDR_ANY); //����ӿ�ΪĬ��?
	/*���������㲥��*/
	ret = setsockopt(client_fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&m_mreq,sizeof(m_mreq));
	if(ret < 0)
	{
		close(client_fd);
		client_fd = -1;
		Log_error("set sock error \n");
		return -4;
	}

	setsockopt(client_fd,SOL_SOCKET,SO_RCVTIMEO, (char *)&timeout,sizeof(struct timeval));

	 //�����߳�
	g_thrUDPReadHdl.iInterval = iInterval;
	int iRet = 0;
	iRet = iPthreadCreate(&g_thrUDPReadHdl,
	                      vpMCProcThread,
	                      PTHREAD_PRI_MAX,
	                      TSK_STACK_SIZE,
	                      &g_thrUDPReadHdl);
	if (0 != iRet)
	{
	    Log_error("Create UDP data thread failed.\n");
	    close(client_fd);
		client_fd = -1;
		return -1;
	}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章