Java Nio UDP广播

扫码查看
本文介绍了Java Nio UDP广播的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试通过广播实现UDP客户端服务器检测.想法如下:我有一个服务器,该服务器绑定到端口12344,一个客户端绑定到端口12345.现在,客户端将广播程序包发送到255.255.255.25512344.服务器应使用以下命令回复该程序包:其他包到IPClient:12345.

I try to implement a UDP client server detection via broadcast. The idea is the following: I have a server, which is bound to port 12344 and a client which is bound to port 12345. Now, the client sends a broadcast package to 255.255.255.255 12344. The server should reply to this package with a other package to IPClient:12345.

该实现使用Java nio.

The implementation uses Java nio.

问题是,在Windows上,服务器获取了软件包,但无法发送答案(我在Wireshark中看不到答案).

The problem is, that on windows, the server gets the packages but cannot(?) send an answer (I don't see the answer in wireshark).

我有以下示例代码:

客户

public final class ASyncUDPClient {
public static void main(String[] args) throws IOException {
  InetSocketAddress hostAddress = new InetSocketAddress("255.255.255.255", 12344);
  System.out.println(hostAddress);

  // Create a non-blocking socket channel
  DatagramChannel channel = DatagramChannel.open();
  channel.socket().setBroadcast(true);
  channel.socket().bind(new InetSocketAddress(getAddress(), 12345));
  channel.configureBlocking(false);

  // Kick off connection establishment
  channel.connect(hostAddress);

  ByteBuffer buffer = getBuffer();

  Selector selector = Selector.open();
  channel.write(buffer);
  System.out.println("data send");
  channel.register(selector, SelectionKey.OP_READ);

  while (true) {
    final int select = selector.select();
    System.out.println("select " + select);
    Iterator selectedKeys = selector.selectedKeys().iterator();
    while (selectedKeys.hasNext()) {
      System.out.println("key selected");
      SelectionKey key = (SelectionKey) selectedKeys.next();
      selectedKeys.remove();

      if (!key.isValid()) {
        continue;
      }

      if (key.isReadable()) {
        System.out.println("read");
      } else if (key.isWritable()) {
        System.out.println("write");
      }
    }
  }
}

private static ByteBuffer getBuffer() throws CharacterCodingException {
  return Charset.forName("UTF-8").newEncoder().encode(CharBuffer.wrap("1234"));
}

private static InetAddress getAddress() throws SocketException {
  final Enumeration<NetworkInterface> networkInterfaces =   NetworkInterface.getNetworkInterfaces();
  NetworkInterface networkInterfaceToUse = null;
  while (networkInterfaces.hasMoreElements()) {
    final NetworkInterface networkInterface = networkInterfaces.nextElement();
    if (networkInterface.getDisplayName().contains("Virtual")) continue;
    if (networkInterface.isVirtual()) continue;
    if (networkInterface.isLoopback()) continue;
    if (!networkInterface.isUp()) continue;
    networkInterfaceToUse = networkInterface;
    System.out.println(networkInterfaceToUse);
  }
  return networkInterfaceToUse.getInterfaceAddresses().get(1).getAddress();
}

}

服务器示例

public class ASyncUDPSvr {

static int BUF_SZ = 1024;
static int port = 12344;

static public void main(String[] args) {
  ASyncUDPSvr svr = new ASyncUDPSvr();
  svr.process();
}

private static InetAddress getAddress() throws SocketException {
  final Enumeration<NetworkInterface> networkInterfaces =    NetworkInterface.getNetworkInterfaces();
  NetworkInterface networkInterfaceToUse = null;
  while (networkInterfaces.hasMoreElements()) {
    final NetworkInterface networkInterface = networkInterfaces.nextElement();
    if (networkInterface.getDisplayName().contains("Virtual")) continue;
    if (networkInterface.isVirtual()) continue;
    if (networkInterface.isLoopback()) continue;
    if (!networkInterface.isUp()) continue;
    networkInterfaceToUse = networkInterface;
    System.out.println(networkInterfaceToUse);
  }
  return networkInterfaceToUse.getInterfaceAddresses().get(1).getAddress();
}

private void process() {
  try {
    Selector selector = Selector.open();
    DatagramChannel channel = DatagramChannel.open();
    InetSocketAddress isa = new InetSocketAddress(getAddress(), port);
    channel.socket().bind(isa);
    channel.configureBlocking(false);
    SelectionKey clientKey = channel.register(selector, SelectionKey.OP_READ);
    clientKey.attach(new Con());
    while (true) {
      try {
        selector.select();
        Iterator selectedKeys = selector.selectedKeys().iterator();
        while (selectedKeys.hasNext()) {
          try {
            SelectionKey key = (SelectionKey) selectedKeys.next();
            selectedKeys.remove();
            if (!key.isValid()) {
              continue;
            }
            if (key.isReadable()) {
              read(key);
              key.interestOps(SelectionKey.OP_WRITE);
            } else if (key.isWritable()) {
              write(key);
              key.interestOps(SelectionKey.OP_READ);
            }
          } catch (IOException e) {
            System.err.println("glitch, continuing... " + (e.getMessage() != null ? e.getMessage() : ""));
          }
        }
      } catch (IOException e) {
        System.err.println("glitch, continuing... " + (e.getMessage() != null ? e.getMessage() : ""));
      }
    }
  } catch (IOException e) {
    System.err.println("network error: " + (e.getMessage() != null ? e.getMessage() : ""));
  }
}

private void read(SelectionKey key) throws IOException {
  DatagramChannel chan = (DatagramChannel) key.channel();
  Con con = (Con) key.attachment();
  con.sa = chan.receive(con.req);
  System.out.println("sender address: " + con.sa + "rcv: " + new   String(con.req.array(), "UTF-8"));
  con.resp = Charset.forName("UTF-8").newEncoder().encode(CharBuffer.wrap("send string"));
}

private void write(SelectionKey key) throws IOException {
  DatagramChannel chan = (DatagramChannel) key.channel();
  Con con = (Con) key.attachment();
  System.out.println("sending data: " + new String(con.resp.array(), "UTF-8") + " to "   + con.sa);
  chan.send(con.resp, con.sa);
  System.out.println("data send");
}

class Con {

  ByteBuffer req;
  ByteBuffer resp;
  SocketAddress sa;

  public Con() {
    req = ByteBuffer.allocate(BUF_SZ);
  }
}
}

推荐答案

InetSocketAddress hostAddress = new InetSocketAddress("255.255.255.255", 12344);
// ...
channel.connect(hostAddress);

问题在这里.您无法连接到广播地址,在任何情况下都没有意义.广播地址不是发送给您,而是发送给您.服务器正在从其自己的绑定地址发送给您.只需删除此行.断开连接后,您将必须使用DatagramChannel.send()而不是write().

The problem is here. You can't connect to the broadcast address, and in any case it doesn't make sense. The broadcast address isn't sending to you, you are sending to it. The server is sending to you from its own bind-address. Just remove this line. You will have to use DatagramChannel.send() rather than write(), as you are unconnected.

这篇关于Java Nio UDP广播的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-16 21:38
查看更多