11

PlayCap ( http://www.signal11.us/oss/playcap/ ) によってネットワーク アドレス 192.168.103.255 ポート 3000 にブロードキャストされる UDP データを受信しようとしています。このアドレスとポートへのバインドに問題があります。ここに私の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 コードもいくつか書きましたが、バインド呼び出しでも失敗します。ただし、このコードは静的 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

(「ac」はファイル名です)。

Java コードの方が重要ですが、私のコード例のどこが間違っているかを教えていただければ幸いです。どんな提案でも大歓迎です。

4

3 に答える 3

13

代わりに、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ます。

于 2012-11-26T04:16:19.007 に答える
3

ブロードキャスト パケットを受信するためにブロードキャスト アドレスにバインドしません。ポートとアドレスにバインドするだけでINADDR_ANY(申し訳ありませんが、Java でそれを表現する方法がわかりません)、ブロードキャスト アドレスでそのポートにパケットを取得します。

于 2012-11-26T04:10:41.010 に答える
0

Datagram コンストラクターは、バインド先のポート番号を取得しているようです。それが役に立ったことを願っています...

于 2012-11-26T04:24:21.460 に答える