Linux&Windows下的IP Multicast 开发

Multicast 不用多说,组播,既然要做multicast开发,肯定得知道multicast是什么;
windows和linux下开发的multicast的代码如下,具体的讲解,看代码注释:
<script type="text/javascript"><!-- google_ad_client = "pub-8565472114859759"; /* 180x150, 创建于 08-7-7 */ google_ad_slot = "4647145443"; google_ad_width = 180; google_ad_height = 150; //--> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
C/C++ code
/*Multicast Client.c support Linux & Windows
*Zhao.kaiyong(a)gmail.com
*http://blog.csdn.net/openhero
*可以转载,可以复制,修改,如果有修改,请给我来一封email:)谢谢
*/
  
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->
#include
< stdio.h >
#include
< stdlib.h >
#include
< string .h >

#ifdef _WIN32
#include
< winsock2.h >
#include
< io.h >
#include
< Ws2tcpip.h >

#pragma comment(lib, "ws2_32.lib")

#else
#include
< sys / types.h >
#include
< sys / socket.h >
#include
< netinet / in .h >
#include
< arpa / inet.h >
#include
< unistd.h >
#include
< errno.h >
#define closesocket close
#endif

#define BUF_SIZE 0x1000

char * host_name = " 224.1.1.3 " ;
int port = 12345 ;

int main( int argc, char * argv[])
{
int loop = 1 ;
/* 多播循环 */
int iter = 0 ;
int from_len;
char buffer[BUF_SIZE];
int socket_descriptor;
struct ip_mreq command;
struct sockaddr_in loc;
struct sockaddr_in rem;

int rec_len = 0 ;
int ptr_point = 0 ;
size_t bytes_written
= 0 ;
int loop_times = 0 ;

int rcv_port_0 = 0 ;
int rcv_port_1 = 0 ;
int first = 0 ;

#ifdef _WIN32
WSADATA wsaData;

if ( WSAStartup(MAKEWORD( 2 , 2 ), & wsaData) != 0 )
{
printf(
" Error in WSAStartup/n " );
exit(
1 );
}
#endif

if (argv[ 1 ])
{
host_name
= argv[ 1 ];
printf(
" %s /n " , host_name);
}
if (argv[ 2 ])
{
port
= atoi(argv[ 2 ]);
printf(
" %d /n " , port);
}

memset(
& loc, 0 , sizeof (loc));
loc.sin_family
= AF_INET;
//这个地方很重要,不然linux下就只能是broadcast;所以必须指定组播的地址;
loc.sin_port = htons(port);
loc.sin_addr.s_addr = inet_addr(host_name);

if ((socket_descriptor = socket(AF_INET, SOCK_DGRAM, 0 )) == - 1 )
{
perror(
" socket " );
exit(EXIT_FAILURE);
}

/* can use the same port in the pc */
loop
= 1 ;
if (setsockopt(socket_descriptor, SOL_SOCKET, SO_REUSEADDR, & loop, sizeof (loop)) < 0 )
{
perror(
" setsockopt:SO_REUSEADDR./n " );
exit(EXIT_FAILURE);
}
else
{
printf(
" setsockopt:SO_REUSEADDR./n " );
}
loop
= 0x1000000 ;// 设置网络的接收buffer的大小
if ( setsockopt( socket_descriptor, SOL_SOCKET, SO_RCVBUF, ( void * ) & loop, sizeof ( loop ) ) < 0 )
{
perror(
" setsockopt:SO_RCVBUF./n " );
exit(EXIT_FAILURE);
}
//由于在前面指定了组播的地址,但是在winodws和linux下不一样,就得这么处理,这个细节来之分析VLC源代码
#if defined( WIN32 ) || defined( UNDER_CE )
/*
* Under Win32 and for multicasting, we bind to INADDR_ANY.
* This is of course a severe bug, since the socket would logically
* receive unicast traffic, and multicast traffic of groups subscribed
* to via other sockets. How this actually works in Winsock, I don't
* know.
*/
if ( IN_MULTICAST( ntohl( loc.sin_addr.s_addr ) ) )
{
struct sockaddr_in stupid = loc;
stupid.sin_addr.s_addr
= INADDR_ANY;

if ( bind( socket_descriptor, ( struct sockaddr * ) & stupid, sizeof ( stupid ) ) < 0 )
{
perror(
" bind socket./n " );
close( socket_descriptor );
return 0 ;
}
}
else
#endif
if (bind(socket_descriptor, ( struct sockaddr * ) & loc, sizeof (loc)) < 0 )
{
perror(
" bind socket./n " );
exit(EXIT_FAILURE);
}



{ //加入组播组,如果有多块网卡,可以用另一个变量来特别设置;
printf(
" %s,%d/n " , host_name, port);
command.imr_multiaddr.s_addr
= inet_addr(host_name);
command.imr_interface.s_addr
= htonl(INADDR_ANY);
if (command.imr_multiaddr.s_addr == - 1 )
{
perror(
" 224.1.1.3 not a legal multicast address./n " );
exit(EXIT_FAILURE);
}
if (setsockopt(socket_descriptor, IPPROTO_IP, IP_ADD_MEMBERSHIP, & command, sizeof (command)) < 0 )
{
perror(
" setsockopt:IP_ADD_MEMBERSHIP. error/n " );
}
}


printf(
" start reciving.../n " );


from_len
= sizeof (rem);
while ( 1 )
{
memset(
& rem, 0 , from_len);
memset(buffer,
0 , BUF_SIZE);
if ( (rec_len = recvfrom(socket_descriptor, buffer, sizeof ( char ) * BUF_SIZE, 0 , ( struct sockaddr * ) & rem, & from_len)) == - 1 ) {
perror(
" recvfrom./n " );
}

printf(
" From host:%s port:%d, len: %d/n " , inet_ntoa(rem.sin_addr), ntohs(rem.sin_port), rec_len);
}
if (setsockopt(socket_descriptor, IPPROTO_IP, IP_DROP_MEMBERSHIP, & command, sizeof (command)) < 0 ) {
perror(
" setsockopt:IP_DROP_MEMBERSHIP./n " );
}
closesocket(socket_descriptor);
exit(EXIT_SUCCESS);
}
注:
1.在windows中不需要特殊的设置网络;
2.在Linux下得特别注意网络的设置,有下面几个环节:
1)查看内核模块,是否已经加载了multicast支持;这个可以通过 在src目录下面 make menuconfig 查看ip 设置栏目看到;
2)查看网络是否已经加载了multicast支持;命令:ip a 可以看到现在网络支持的各个功能;
3)添加multicast 网络路由:net add -net 224.0.0.0 netmask 240.0.0.0 dev eth0
这样才能启动网络的multicast路由支持,不然只能当作broadcast处理。


你可能感兴趣的:(windows)