2014-02-07 89 views
4

我有一個設備,它通過在端口4930上發送一個廣播數據包到255.255.255.255而發現,設備通過在端口4930上發送數據包回到255.255.255.255來響應。在C++中接收到地址爲255.255.255.255的廣播數據包

我有C++代碼片段可發送一個數據包到255.255.255.255端口4930(源和目標端口),但它不能接收的數據包從廣播地址255.255.255.255回來。

我可以看到設備工作正常,wireshark可以看到來回的數據包,設備提供的專有軟件可以很好地發現設備,問題在於C++程序,所以請繼續關注主題你的迴應。

現在,正如我剛纔所說,我可以發送一個數據包只要找到,但首先,我不能綁定的IP地址255.255.255.255接收數據包。我可以將多播地址更改爲239.255.255.250,套接字將會綁定,但我需要地址255.255.255.255。

我的代碼片斷如下,我使用VC++ 2010

bool CPTUProgramDlg::FindPTU(u_short port, const char * Destaddress){ 
    { 
     //Data to send 
     char packet_data[10] = {0x44,0x43,0x55,0x44,0x5f,0x50,0x49,0x4e,0x47,0x00}; 
     int packet_size=10; 

     SOCKET sock; 
     struct sockaddr_in addr; 

     sock = socket(AF_INET, SOCK_DGRAM, 0); 

     // set SO_BROADCAST on a socket to true (1): (so we can transmit to 255 addr) 
     //In order to use broadcast the options of socket must change 
     char broadcastON = 1; 
     setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &broadcastON, sizeof broadcastON); 

     if (sock < 0) 
      return false; 

     addr.sin_family = AF_INET; 
     addr.sin_port = htons(port); 
     addr.sin_addr.s_addr = inet_addr(Destaddress); // Specify dest IP 

     sendto(sock, packet_data, packet_size, 0, (struct sockaddr*)&addr, sizeof(addr)); 

     if (bind(sock,(struct sockaddr*) &addr,sizeof(addr)) != -1){ 
      char Buff[512]; 
      recv(sock,Buff,512,0); 
     } 

     closesocket(sock); 
    } 

    return 1; 
} 

Wireshark的屏幕截圖,以證明數據包正在發送:

enter image description here

+0

嘗試在0.0.0.0上綁定,並按目標IP地址執行過濾。例如。通過使用recvfrom而不是recv ... – bbonev

+1

順便說一句。這種類型的數據包是廣播,而不是多播。我從屏幕截圖中看到,設備從端口4930響應端口4930 - 您可能還需要使用兩個不同的套接字 - 一個用於發送,一個用於接收。 – bbonev

+0

在0.0.0.0上綁定成功,但recvfrom返回-1,我添加的代碼是sockaddr * from = new sockaddr [1];如果(recvfrom的(襪子,BUFF,512,0,從(INT *)的sizeof(SOCKADDR))<0){返回0;} – ALM865

回答

3

從Wireshark的輸出它的看出,特殊設備正在使用廣播進行通信,並將使用與源和目標相同的端口號。

普通socket通信將需要使用匹配的端口號,但是廣播消息不能在同一插座進行交換,尤其是當作爲使用Wireshark看到的端口號不匹配。

綁定上255.255.255.255(INADDR_BROADCAST)通常應該工作,但可以通過你的操作系統權限和權限的限制。

您可以嘗試使用兩個套接字來解決問題 - 一個用於接收,一個用於發送。當然,監聽套接字必須先設置並綁定到0.0.0.0(INADDR_ANY)和端口4930.在這種情況下,沒有簡單的方法來過濾目標地址(因爲我錯誤地寫在我的評論中),因爲大多數標準套接字API不要提供從套接字獲取目標地址的方法。在Linux上,有一個例外 - IP_PKTINFO at SOL_IP ...

通過使用recvfrom,您將獲得響應設備的源單播地址。你必須注意,如果你的網絡上有更多這樣的設備,你將得到不止一個響應。

+0

再次感謝bbonev! – ALM865