2012-11-26 76 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数据报构造函数将端口号绑定到。希望有帮助...

相关问题