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;
}
私はWindows7マシンを使用しています。 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();
}
}
データグラムソケットの引数なしコンストラクターを呼び出すと、ランダムで使用可能なポートにバインドされます。バインドされると、さらに(再)バインドしようとすると、ソケット例外がスローされます(表示されていたエラーが発生します)。バインディングを「延期」するには、代わりに、バインドされていない状態でデータグラムソケットを作成し(コンストラクターでnullを渡すことにより)、後でbind
を呼び出します。
ブロードキャストパケットを受信するためにブロードキャストアドレスにバインドすることはありません。ポートとアドレスにバインドするだけですINADDR_ANY
(申し訳ありませんが、Javaでそれを表現する方法がわかりません)。ブロードキャストアドレスのそのポートにパケットが届きます。
そのように見えます Datagramコンストラクターはバインドするポート番号を取得します。それが役に立ったことを願っています...