个人觉得的有用的文档,贴出来和大家分享

组播和广播

上一篇 / 下一篇  2007-07-09 20:07:28 / 个人分类:c++

IP组播地址用于标识一个IP组播组。IANAD类地址空间分配给IP组播,范围从224.0.0.0239.255.255.255IP组播地址前四位均为1110

  从224.0.0.0224.0.0.255IANA保留为网络协议使用。例如:244.0.0.1全主机组244.0.0.2全多播路由器组244.0.0.3DVMRP路由器组244.0.0.5OSPF路由器组。在这一范围的多播包不会被转发出本地网络,也不会考虑多播包的TTL值。
  地址从239.0.0.0239.255.255.255作为管理范围地址,保留为私有内部域使用。
  如下图所示,以太网和FDDIMAC地址01:00:5E:00:00:0001:00:5E:7F:FF:FF用于将三层IP组播地址映射为二 层地址,即IP组播地址中的低23位放入IEEE MAC地址的低23位。IP组播地址有28位地址空间,但只有23位被映射到IEEE MAC地址,这样会有32IP组播地址映射到同一MAC地址上。

 

这是我的一段代码,但是不起作用! 
  SOCKET     s;  
  struct   ip_mreq   ipmr;  
  struct   sockaddr_in     local,from;  
  char     recvbuf[2480];  
  int     len=sizeof(struct   sockaddr_in);  
  long   ret;  
   
  s=socket(AF_INET,SOCK_DGRAM,0);  
  local.sin_family=AF_INET;  
  local.sin_addr.s_addr=htonl(INADDR_ANY);  
  local.sin_port=htons(5520);  
   
  ipmr.imr_multiaddr.s_addr=inet_addr("224.2.223.193");  
  ipmr.imr_interface.s_addr=htonl(INADDR_ANY);  
   
  bind(s,(SOCKADDR   *)&local,sizeof(local));  
  if   (setsockopt(s,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char   *)&ipmr,sizeof(ipmr))==SOCKET_ERROR)   {  
  TRACE("SetSocketOpt
失败\n");  
  return;  
  }  
  else   {  
  TRACE("
设置组播成功\n");  
  }  
   
   
  while   (1)   {  
  if   ((ret=recvfrom(s,recvbuf,2480,0,(struct   sockaddr   *)&from,&len))==SOCKET_ERROR)   {  
  TRACE("recvfrom   failed\n");  
                  }  
  else   {  
  TRACE("TestSocket---------%s,length=%d\n",inet_ntoa(from.sin_addr),ret);  
  }  
  }
问题点数:100、回复次数:3Top

1xuying()回复于2002-06-12 10:29:42得分60

组播不需要什么特殊的设置。下面是的代码在win2k  局域网环境下试验通过:  
   
  //
发送方程序  sender.c  
   
  #include   <winsock2.h>  
  #include   <ws2tcpip.h>  
  #include   <stdio.h>  
   
  #define   BUFFSIZE   2048  
  #define   IP_ADDR             "224.8.8.1"            
  #define   DEST_PORT                   8888  
   
  int   main(int   argc,char   *argv[])  
  {  
          int   sockfd;  
          struct   sockaddr_in   addr;  
          char   szError[100];  
  char   buf[]   =   "Hello,   World!";  
  int   ttl   =   255   ;   //   Arbitrary   TTL   value.  
   
          WSADATA   WSAData;  
          WORD     wVersionRequested;  
          wVersionRequested   =   MAKEWORD(2,   2);  
          if   (WSAStartup   (wVersionRequested   ,   &WSAData)   !=   0)    
          {  
                  printf   ("recver:Initialize   Winsock   error!");  
                  exit(1);  
          }  
          if   (LOBYTE(WSAData.wVersion)   !=   2   ||   HIBYTE(WSAData.wVersion)   !=   2   )   {  
                  WSACleanup(   );  
                  printf   ("setsockopt   failed!   Error:   %d",   WSAGetLastError   ());  
                  exit(1);  
          }    
   
          addr.sin_family   =   AF_INET;  
          addr.sin_port   =   htons(DEST_PORT);  
          addr.sin_addr.s_addr   =   inet_addr(IP_ADDR);  
           
          if   ((sockfd=socket(AF_INET,SOCK_DGRAM,0))   <   0)   {  
                  printf("sender:new   a   socket   error!\n");  
                  exit(1);          
          }  
   
  if(setsockopt(sockfd,   IPPROTO_IP,   IP_MULTICAST_TTL,   (char   *)&ttl,   sizeof(ttl))!=0)    
  {  
  printf("error   setsockopt   IP_MULTICAST_TTL\n");  
  exit(1);  
  }  
  /*  
          if   (bind(sockfd,(struct   sockaddr   *)&recver_addr,sizeof(recver_addr))   <   0)   {  
                  closesocket(sockfd);  
                  printf("recver:bind   socket   error!\n");  
                  exit(1);          
          }  
  */  
           
      if   (sendto   (sockfd,   buf,   sizeof(buf)   ,   0,   (struct   sockaddr   *)&addr,   sizeof(addr))  
  ==   SOCKET_ERROR)  
      {  
          wsprintf   (szError,   TEXT("sendto   failed!   Error:   %d"),    
                              WSAGetLastError   ());  
          MessageBox   (NULL,   szError,   TEXT("Error"),   MB_OK);  
          closesocket   (sockfd);  
          return   FALSE;  
      }  
      else  
      {  
          printf("send   ok\n");  
      }  
   
  //   Close   Sock.  
  closesocket   (sockfd);  
  WSACleanup   ();  
  return   0;  
  }  
   
  //  
接收方程序  receivers.c  
   
  //#include   <windows.h>  
  #include   <winsock2.h>  
  #include   <ws2tcpip.h>  
  #include   <stdio.h>  
   
  #define   BUFFSIZE   2048  
  #define   RECV_IP_ADDR             "224.8.8.1"            
  #define   DEST_PORT                   8888  
   
  int   main(int   argc,char   *argv[])  
  {  
          int   sockfd;  
          int   sock_reuse   =   1;  
          struct   ip_mreq   multicast;  
          struct   sockaddr_in   recver_addr;  
          char   szError[100];  
   
      int   index   =   0,                                             //   Integer   index  
              iRecvLen;                                               //   Length   of   recv_sin  
      char   szMessageA[1024*320];                               //   ASCII   string    
      TCHAR   szMessageW[1024*320];                             //   Unicode   string  
           
          WSADATA   WSAData;  
          WORD     wVersionRequested;  
          wVersionRequested   =   MAKEWORD(2,   2);  
          if   (WSAStartup   (wVersionRequested   ,   &WSAData)   !=   0)    
          {  
                  printf   ("recver:Initialize   Winsock   error!");  
                  exit(1);  
          }  
          if   (LOBYTE(WSAData.wVersion)   !=   2   ||   HIBYTE(WSAData.wVersion)   !=   2   )   {  
                  WSACleanup(   );  
                  printf   ("setsockopt   failed!   Error:   %d",   WSAGetLastError   ());  
                  exit(1);  
          }    
   
          multicast.imr_multiaddr.s_addr   =   inet_addr(RECV_IP_ADDR);  
          multicast.imr_interface.s_addr   =   htonl(INADDR_ANY);  
          recver_addr.sin_family   =   AF_INET;  
          recver_addr.sin_port   =   htons(DEST_PORT);  
          recver_addr.sin_addr.s_addr   =   INADDR_ANY;  
           
          if   ((sockfd=socket(AF_INET,SOCK_DGRAM,0))   <   0)   {  
                  printf("recver:new   a   socket   error!\n");  
                  exit(1);          
          }  
          if   (setsockopt(sockfd,   SOL_SOCKET,   SO_REUSEADDR,   (char   *)&sock_reuse,   sizeof(sock_reuse))   <   0)   {  
                      printf("recver   :   socket   options   set   error");  
                      exit(1);  
          }  
   
          if   (bind(sockfd,(struct   sockaddr   *)&recver_addr,sizeof(recver_addr))   <   0)   {  
                  closesocket(sockfd);  
                  printf("recver:bind   socket   error!\n");  
                  exit(1);          
          }  
           
          if   (setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char   *)&multicast,sizeof(multicast))   <   0   )   {  
                  sprintf   (szError,   TEXT("setsockopt   failed!   Error:   %d"),   WSAGetLastError   ());  
                  printf("%s\n",   szError);  
                  closesocket(sockfd);  
                  exit(1);  
          }  
   
  printf("Receive   on   %s:%d\n",   RECV_IP_ADDR,   DEST_PORT);  
      iRecvLen   =   sizeof   (recver_addr);  
      memset(szMessageA,   0,   sizeof(szMessageA));  
      //   Receive   data   from   the   multicasting   group   server.  
      if   (recvfrom   (sockfd,    
                                  szMessageA,  
                                  sizeof(szMessageA),                    
                                  0,  
                                  (struct   sockaddr   FAR   *)   &recver_addr,  
                                  &iRecvLen)   ==   SOCKET_ERROR)  
      {  
          wsprintf   (szError,   TEXT("recvfrom   failed!   Error:   %d"),    
                              WSAGetLastError   ());  
          MessageBox   (NULL,   szError,   TEXT("Error"),   MB_OK);  
          closesocket   (sockfd);  
          return   FALSE;  
      }  
      else  
      {  
          //   Convert   the   ASCII   string   to   a   Unicode   string.  
          for   (index   =   0;   index   <=   sizeof   (szMessageA);   index++)  
              szMessageW[index]   =   szMessageA[index];  
   
          MessageBox   (NULL,   szMessageW,   TEXT("Info"),   MB_OK);  
      }  
   
      //   Disable   receiving   on   Sock   before   closing   it.  
      shutdown   (sockfd,   0x00);  
   
      //   Close   Sock.  
      closesocket   (sockfd);  
   
      WSACleanup   ();  
          return   0;  
  }  
 Top

2djhdu(小火花)回复于2002-06-12 10:45:16得分0

哦,是不是只要发送给这个组播地址,其它组播接收程序就都可以收到?Top

3xuying()回复于2002-06-12 11:02:33得分40

发送程序很简单,只要给组播地址发就可以了。 
 
接收的时候要先加入组播组。就是下面这一段程序:  
  if   (setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char   *)&multicast,sizeof(multicast))   <   0   )   {  
                  sprintf   (szError,   TEXT("setsockopt   failed!   Error:   %d"),   WSAGetLastError   ());  
                  printf("%s\n",   szError);  
                  closesocket(sockfd);  
                  exit(1);  
 Top

4xuying()回复于2002-06-12 11:03:34得分0

发送程序很简单,只要给组播地址发就可以了。 
 
接收的时候要先加入组播组。就是下面这一段程序:  
  if   (setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char   *)&multicast,sizeof(multicast))   <   0   )   {  
                  sprintf   (szError,   TEXT("setsockopt   failed!   Error:   %d"),   WSAGetLastError   ());  
                  printf("%s\n",   szError);  
                  closesocket(sockfd);  
                  exit(1);  

Linux网络编程一步一步学-UDP方式广播通讯

关键词broadcast  UDP  广播  recvfrom  sendto                                         

和前一篇文章<Linux网络编程一步一步学-UDP方式点对点通讯>一样,只是在客户端源代码里加一行设置socket属性为广播方式即可。

需要加的一句是:
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(yes));

源代码变成下面的:


#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <errno.h>
#include <stdlib.h>
#include <arpa/inet.h>

/*********************************************************************
*filename: broadc-udpclient.c
*purpose:
基本编程步骤说明,演示了UDP编程的广播客户端编程步骤
*tidied by: zhoulifa(zhoulifa@163.com)
周立发(http://zhoulifa.bokee.com)
Linux
爱好者Linux知识传播者SOHO族 开发者 最擅长C语言
*date time:2007-01-24 21:30:00
*Note:
任何人可以任意复制代码并运用这些文档,当然包括你的商业用途
*
但请遵循GPL
*Thanks to: Google.com
*Hope:
希望越来越多的人贡献自己的力量,为科学技术发展出力
*
科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!
*********************************************************************/
int main(int argc, char **argv)
{
struct sockaddr_in s_addr;
int sock;
int addr_len;
int len;
char buff[128];
int yes;

/*
创建socket */
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("socket");
exit(errno);
} else
printf("create socket.\n\r");

/*
设置通讯方式对广播,即本程序发送的一个消息,网络上所有主机均可以收到*/
yes = 1;
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(yes));
/*
唯一变化就是这一点了*/

/*
设置对方地址和端口信息*/
s_addr.sin_family = AF_INET;
if (argv[2])
s_addr.sin_port = htons(atoi(argv[2]));
else
s_addr.sin_port = htons(7838);
if (argv[1])
s_addr.sin_addr.s_addr = inet_addr(argv[1]);
else {
printf("
消息必须有一个接收者!\n");
exit(0);
}

/*
发送UDP消息*/
addr_len = sizeof(s_addr);
strcpy(buff, "hello i'm here");
len = sendto(sock, buff, strlen(buff), 0,
(struct sockaddr *) &s_addr, addr_len);
if (len < 0) {
printf("\n\rsend error.\n\r");
return 3;
}

printf("send success.\n\r");
return 0;
}


编译这个程序用下列命令:
gcc -Wall broadc-udpclient.c -o client
运行程序用下列命令:
./client 192.168.0.255 7838

就会往192.168.0网络内所有主机发消息。

其它主机如果运行了服务端:
./server
自己的IP地址7838
则都会收到上述客户端发的消息了。

 


TAG:

 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

Open Toolbar