java - 绑定(bind)特定IP地址和端口接收UDP数据

标签 java c udp bind

我正在尝试接收由 PlayCap ( http://www.signal11.us/oss/playcap/ ) 广播到网络地址 192.168.103.255 端口 3000 的 UDP 数据。我在绑定(bind)到此地址和端口时遇到问题。这是我的 Java 代码:

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 代码来创建一个套接字并绑定(bind)到这个地址和端口,但它在绑定(bind)调用时也失败了。但是,此代码将绑定(bind)到我的静态 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 代码更重要,但我很乐意知道我的代码示例中哪里出错了。非常感谢任何建议。

最佳答案

请尝试使用您的 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();
    }
}

为数据报套接字调用无参数构造函数将导致它绑定(bind)到一个随机的可用端口。一旦绑定(bind),进一步尝试(重新)绑定(bind)将抛出套接字异常(出现您看到的错误)。要“延迟”绑定(bind),您需要在未绑定(bind)状态下创建数据报套接字(通过在构造函数中传递 null),然后稍后调用 bind

关于java - 绑定(bind)特定IP地址和端口接收UDP数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13558522/

相关文章:

Python:在 Windows 上获取 UDP 广播/socket.recvcmsg() 的发送者

java - 通过互联网与 Android 手机和 PC 进行 2 种方式通信

java - 如何清空原始数组?

c - 使用 FUSE 在 C 中编写一个简单的文件系统

c - 递归方法的二分法?

c - __attribute__ ((__packed__)) 在 typedef 声明中被忽略了吗?

java - 如何使用java以相反的顺序对数组进行排序?

java - 如何在 View 之间传输数据?

java - 在java中使用泛型接口(interface)作为返回类型

c++ - UDP:客户端在服务器之前启动