我使用Selector
和频道(ServerSocketChannel
,DatagramChannel
)在同一套接字中创建udp / tcp heandler。当我将DatagramPacket
的数据包发送到服务器时,服务器会注册许多选择器(2-8,每次都不同),每次服务器都会处理这些密钥。因此,此查询在使用trim()
后会显示空字段,但其中一个键具有查询文本。
服务器
public class Server extends Thread {
public void run() {
SocketAddress port = new InetSocketAddress(ReaderProperty.getPropertyPort());
try {
Selector selector = Selector.open();
ServerSocketChannel tcpServer = ServerSocketChannel.open();
tcpServer.socket().bind(port);
tcpServer.configureBlocking(false);
tcpServer.register(selector, SelectionKey.OP_ACCEPT);
DatagramChannel udpServer = DatagramChannel.open();
udpServer.socket().bind(port);
udpServer.configureBlocking(false);
udpServer.register(selector, SelectionKey.OP_READ);
while(true) {
try {
selector.select();
Set<SelectionKey> keys = selector.selectedKeys();
for (Iterator<SelectionKey> i = keys.iterator(); i.hasNext();) {
SelectionKey key = i.next();
i.remove();
Channel c = key.channel();
if (key.isAcceptable() && c == tcpServer) {
new TCPResponse(tcpServer.accept().socket()).start();
} else if (key.isReadable() && c == udpServer) {
new UDPResponse(udpServer, key.channel()).start();
}
}
keys.clear();
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
UDPRequest
public class UDPRequest {
public UDPRequest(String server, int port, String query) {
DatagramSocket client = null;
try {
client = new DatagramSocket();
byte[] sendByte = query.getBytes();
byte[] receiveByte = new byte[32];
DatagramPacket sender = new DatagramPacket(sendByte, sendByte.length, InetAddress.getByName(server), port);
client.send(sender);
DatagramPacket receiver = new DatagramPacket(receiveByte, receiveByte.length);
client.receive(receiver);
ByteBuffer buf = ByteBuffer.allocate(32);
buf.clear();
buf = ByteBuffer.wrap(receiver.getData());
String receiveLine = new String(buf.array(), Charset.forName("UTF-8")).trim();
System.out.println("IP address or DOMAIN NAME: " + receiveLine);
if (receiveLine.equals("true")) {
new TCPRequest(server, port, query);
}
} catch(Exception e) {
e.getStackTrace();
}
if (client != null) {
client.close();
}
}
UDPResponse
public class UDPResponse extends Thread {
private DatagramChannel channel = null;
private SelectableChannel selectableChannel = null;
public UDPResponse(DatagramChannel channel, SelectableChannel selectableChannel) {
super("UDPResonse");
this.channel = channel;
this.selectableChannel = selectableChannel;
}
@Override
public void run() {
try {
ByteBuffer buf = ByteBuffer.allocate(32);
buf.clear();
InetSocketAddress address = (InetSocketAddress) ((DatagramChannel) selectableChannel).receive(buf);
String inputLine = new String(buf.array(), Charset.forName("UTF-8"));
String outputLine = Utils.processCommand(inputLine.trim());
buf.clear();
try {
buf.put(outputLine.getBytes());
} catch (BufferOverflowException overflow) {
buf.put("true".getBytes());
}
buf.flip();
try {
channel.send(buf, address);
} catch (NullPointerException ignored) {
}
} catch (IOException e) {
e.printStackTrace();
}
}
为什么我向服务器发出一个查询,但服务器一次获得2-8个连接?
UPD: 只有在忽略这些空请求时才找到解决方案:
if (inputLine.trim().length() != 0) {
//process...
}