socket udp廣播和多播的簡單實現


UDP廣播與多播

作者:legend

QQ:1327706646

使用UDP協議進行信息的傳輸之前不需要建議連接。換句話說就是客戶端向服務器發送信息,客戶端只需要給出服務器的ip地址和端口號,然后將信息封裝到一個待發送的報文中並且發送出去。至於服務器端是否存在,或者能否收到該報文,客戶端根本不用管。

通常我們討論的udp的程序都是一對一的單播程序。本章將討論一對多的服務:廣播(broadcast)、多播(multicast)。對於廣播,網絡中的所有主機都會接收一份數據副本。對於多播,消息只是發送到一個多播地址,網絡知識將數據分發給哪些表示想要接收發送到該多播地址的數據的主機。總得來說,只有UDP套接字允許廣播或多播。

UDP廣播

廣播UDP與單播UDP的區別就是IP地址不同,廣播使用廣播地址255.255.255.255,將消息發送到在同一廣播網絡上的每個主機。值得強調的是:本地廣播信息是不會被路由器轉發。當然這是十分容易理解的,因為如果路由器轉發了廣播信息,那么勢必會引起網絡癱瘓。這也是為什么IP協議的設計者故意沒有定義互聯網范圍的廣播機制。

廣播地址通常用於在網絡游戲中處於同一本地網絡的玩家之間交流狀態信息等。廣播就不在寫演示程序了,讀者可以將ECHO程序的ip地址改為廣播地址即可。

其實廣播顧名思義,就是想局域網內所有的人說話,但是廣播還是要指明接收者的端口號的,因為不可能接受者的所有端口都來收聽廣播。

UDP多播

  1. 同樣的UDP多播也要指明接受者的端口號,而且與廣播相似的是多播與單播之間的區別還在於地址。ipv4中的多播地址范圍是:224.0.0.0到239.255.255.255。在JAVA中,多播一樣十分好實現,要實現多播,就要用到MulticastSocket類,其實該類就是DatagramSocket的子類,在使用時除了多播自己的一些特性外,把它當做DatagramSocket類使用就可以了。下面將給出一個簡單的多播接受數據的例子:
    1. // 發送端   
    2. #include <iostream>   
    3. #include <stdio.h>   
    4. #include <sys/socket.h>   
    5. #include <unistd.h>   
    6. #include <sys/types.h>   
    7. #include <netdb.h>   
    8. #include <netinet/in.h>   
    9. #include <arpa/inet.h>   
    10. #include <string.h>   
    11.   
    12.   
    13. using namespace std;  
    14.   
    15. int main()  
    16. {  
    17.     setvbuf(stdout, NULL, _IONBF, 0);   
    18.     fflush(stdout);   
    19.   
    20.     int sock = -1;  
    21.     if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)   
    22.     {     
    23.         cout<<"socket error"<<endl;   
    24.         return false;  
    25.     }     
    26.       
    27.     const int opt = 1;  
    28.     //設置該套接字為廣播類型,   
    29.     int nb = 0;  
    30.     nb = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&opt, sizeof(opt));  
    31.     if(nb == -1)  
    32.     {  
    33.         cout<<"set socket error..."<<endl;  
    34.         return false;  
    35.     }  
    36.   
    37.     struct sockaddr_in addrto;  
    38.     bzero(&addrto, sizeof(struct sockaddr_in));  
    39.     addrto.sin_family=AF_INET;  
    40.     addrto.sin_addr.s_addr=htonl(INADDR_BROADCAST);  
    41.     addrto.sin_port=htons(6000);  
    42.     int nlen=sizeof(addrto);  
    43.   
    44.     while(1)  
    45.     {  
    46.         sleep(1);  
    47.         //從廣播地址發送消息   
    48.         char smsg[] = {"abcdef"};  
    49.         int ret=sendto(sock, smsg, strlen(smsg), 0, (sockaddr*)&addrto, nlen);  
    50.         if(ret<0)  
    51.         {  
    52.             cout<<"send error...."<<ret<<endl;  
    53.         }  
    54.         else  
    55.         {         
    56.             printf("ok ");    
    57.         }  
    58.     }  
    59.   
    60.     return 0;  
    61. }  
    1. // 接收端 http://blog.csdn.net/robertkun   
    2.   
    3. #include <iostream>   
    4. #include <stdio.h>   
    5. #include <sys/socket.h>   
    6. #include <unistd.h>   
    7. #include <sys/types.h>   
    8. #include <netdb.h>   
    9. #include <netinet/in.h>   
    10. #include <arpa/inet.h>   
    11. #include <string.h>   
    12.   
    13.   
    14. using namespace std;  
    15.   
    16. int main()  
    17. {  
    18.     setvbuf(stdout, NULL, _IONBF, 0);   
    19.     fflush(stdout);   
    20.   
    21.     // 綁定地址   
    22.     struct sockaddr_in addrto;  
    23.     bzero(&addrto, sizeof(struct sockaddr_in));  
    24.     addrto.sin_family = AF_INET;  
    25.     addrto.sin_addr.s_addr = htonl(INADDR_ANY);  
    26.     addrto.sin_port = htons(6000);  
    27.       
    28.     // 廣播地址   
    29.     struct sockaddr_in from;  
    30.     bzero(&from, sizeof(struct sockaddr_in));  
    31.     from.sin_family = AF_INET;  
    32.     from.sin_addr.s_addr = htonl(INADDR_ANY);  
    33.     from.sin_port = htons(6000);  
    34.       
    35.     int sock = -1;  
    36.     if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)   
    37.     {     
    38.         cout<<"socket error"<<endl;   
    39.         return false;  
    40.     }     
    41.   
    42.     const int opt = 1;  
    43.     //設置該套接字為廣播類型,   
    44.     int nb = 0;  
    45.     nb = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&opt, sizeof(opt));  
    46.     if(nb == -1)  
    47.     {  
    48.         cout<<"set socket error..."<<endl;  
    49.         return false;  
    50.     }  
    51.   
    52.     if(bind(sock,(struct sockaddr *)&(addrto), sizeof(struct sockaddr_in)) == -1)   
    53.     {     
    54.         cout<<"bind error..."<<endl;  
    55.         return false;  
    56.     }  
    57.   
    58.     int len = sizeof(sockaddr_in);  
    59.     char smsg[100] = {0};  
    60.   
    61.     while(1)  
    62.     {  
    63.         //從廣播地址接受消息   
    64.         int ret=recvfrom(sock, smsg, 100, 0, (struct sockaddr*)&from,(socklen_t*)&len);  
    65.         if(ret<=0)  
    66.         {  
    67.             cout<<"read error...."<<sock<<endl;  
    68.         }  
    69.         else  
    70.         {         
    71.             printf("%s\t", smsg);     
    72.         }  
    73.   
    74.         sleep(1);  
    75.     }  
    76.   
    77.     return 0;  
    78. }  
  2. 自已在Linux虛擬機下測試可以成功, 前提是要把主機設置在同一網段內, 還有就是不要忘記關閉Linux的防火牆.. 可以使用setup命令進行設置。

    (我在測試的時候只能發送不收接收,折磨了我半天,后來才想到是Linux防火牆的問題。。)

     

    關於虛擬機的網卡配置,建議選擇橋接模式。NAT的模式的話,是受限制的,可能會收不到廣播消息。

    具體的參考網上的文章吧。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM