2012-11-26 67 views
9

我試圖通過PlayCap(http://www.signal11.us/oss/playcap/)接收廣播到網絡地址192.168.103.255端口3000的UDP數據。我遇到了綁定到這個地址和端口的問題。這是我的Java代碼:綁定到特定的IP地址和端口以接收UDP數據

public static void main(String[] args) { 
    try { 
     DatagramSocket s = new DatagramSocket(); 
     InetSocketAddress address = new InetSocketAddress("192.168.103.255", 3000); 
     s.bind(address); 

     byte buffer[] = new byte[1024]; 
     DatagramPacket packet = new DatagramPacket(buffer, buffer.length); 

     System.out.println("Waiting..."); 
     s.receive(packet); 
     System.out.println("Received!"); 

    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

這將返回錯誤:

java.net.SocketException: already bound 
    at java.net.DatagramSocket.bind(Unknown Source) 
    at runner.main(runner.java:12) 

我已經運行命令 「netstat的-a -n」,既不地址192.168.103.255和端口3000在任何地方上市輸出,所以我不認爲這個端口已經被使用。事實上,我嘗試使用任何地址/端口組合(包括我的靜態IP地址)出現此錯誤。

我也寫了一些C代碼來創建一個套接字並綁定到這個地址和端口,但是它在綁定調用中也失敗了。但是,此代碼將綁定到我的靜態IP地址(192.168.1.149)上的端口。代碼如下:

#include <stdio.h> 
#include <sys/types.h> 
#include <winsock.h> 
#include <unistd.h> 

#define a1 192 
#define a2 168 
#define a3 103 
#define a4 255 
#define PORT 3000 

int main() { 

    /* Open windows connection */ 
    WSADATA w; 
    if (WSAStartup(0x0101, &w) != 0) 
    { 
     printf("Could not open Windows connection.\n"); 
     exit(0); 
    } 

    /* Clear out server struct */ 
    SOCKADDR_IN server; 
    memset((void *)&server, '\0', sizeof(struct sockaddr_in)); 

    /* Set family and port */ 
    server.sin_family = AF_INET; 
    server.sin_port = htons(PORT); 
    server.sin_addr.S_un.S_un_b.s_b1 = (unsigned char)a1; 
    server.sin_addr.S_un.S_un_b.s_b2 = (unsigned char)a2; 
    server.sin_addr.S_un.S_un_b.s_b3 = (unsigned char)a3; 
    server.sin_addr.S_un.S_un_b.s_b4 = (unsigned char)a4; 

    /* Open a datagram socket */ 
    int sd = socket(AF_INET, SOCK_DGRAM, 0); 
    if (sd == INVALID_SOCKET) 
    { 
     printf("Could not create socket.\n"); 
     WSACleanup(); 
     exit(0); 
    } 

    /* Bind address to socket */ 
    if (bind(sd, (struct sockaddr *)&server, sizeof(SOCKADDR_IN)) == -1) 
    { 
     printf("Could not bind name to socket.\n"); 
     closesocket(sd); 
     WSACleanup(); 
     exit(0); 
    } 

    /* Receive */ 
    char data[1024]; 
    printf("Waiting to receive...\n"); 
    if (recv(sd, (char *)&data, (int)sizeof(data), 0)) 
    { 
     printf("Error receiving data.\n"); 
     closesocket(sd); 
     WSACleanup(); 
     exit(0); 
    } 

    printf("Data: %s", data); 

    return 0; 
} 

我使用的是Windows 7機器。我在Eclipse中運行Java代碼。我正在用MinGW使用以下命令編譯C代碼:

gcc a.c -lws2_32 

(「a.c」是文件名)。

雖然Java代碼更重要,但我很樂意知道我的代碼示例中哪裏出了問題。任何建議都非常感謝。

+0

什麼是Win32錯誤?爲什麼靜態IP? –

+0

爲什麼你說「廣播」,然後靜態IP? –

回答

12

試試這個爲你的Java代碼來代替:

public static void main(String[] args) { 
    try { 
     DatagramSocket s = new DatagramSocket(null); 
     InetSocketAddress address = new InetSocketAddress("192.168.103.255", 3000); 
     s.bind(address); 

    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

呼喚一個數據報套接字的無參數的構造會導致它綁定到一個隨機的,可用的端口。一旦綁定,進一步嘗試(重新)綁定將會拋出一個套接字異常(帶有您所看到的錯誤)。爲了「推遲」綁定,您可以創建處於未綁定狀態的數據報套接字(通過在構造函數中傳遞null),然後稍後調用bind

+0

獲取此錯誤:java.net.BindException:無法分配請求的地址:無法在java.net.DualStackPlainDatagramSocketImpl處綁定 \t。socketBind(本機方法) \t在java.net.DualStackPlainDatagramSocketImpl.bind0(來源不明) \t在java.net.AbstractPlainDatagramSocketImpl.bind(來源不明) \t在java.net.DatagramSocket.bind(來源不明) \t在runner.main(runner.java:11)​​ – ajlitzau13

+0

@ ajlitzau13:我的答案解釋了*爲什麼*就是這樣。 –

+0

嘗試綁定到您的默認界面,以消除IPv6問題(刪除互聯網地址,只使用端口)。 – Perception

4

您不綁定廣播地址來接收廣播數據包。只需綁定到端口和地址INADDR_ANY(對不起,不知道如何用Java表示),並且您將在廣播地址上獲取該端口的數據包。

+0

這裏聽什麼?接近-1 ... –

+0

@KirillKobelev:我認爲「監聽端口/地址」被理解爲對特定地址的綁定,但我澄清了措辭。 –

+0

現在聽起來好多了。 –

0

appears that數據報構造函數將端口號綁定到。希望有幫助...

相關問題