私はNIOで練習しており、クライアント側とサーバー側で簡単なアプリケーションを作成しようとしています。このアプリはちょうどクライエンからサーバーにメッセージをバイト単位で送信し、応答として他のメッセージを取得する必要があります。私のコードはここにあります。しかし、私にはさまざまな問題があります。NIOでの読み書きに関する多くの問題
時には、readMessage()
メソッドからのint bytesRead = socketChannel.read(byteBuffer);
またはbytesRead = socketChannel.read(byteBuffer);
の行は、ゼロバイトの無限シーケンスを読み取り、OOMエラーをスローします。
{"class":"server.PasswordHashResponse","xoredHash":"RV5GX1JVAwADBEVZWwFGTAhZQ1FGX1tYQ11ZVwA\u003d"}
ではなく、サーバーからの応答がthatのように表示されることがあります。
時々応答は、このような奇妙な尾を持っている:両方のサーバー{"class":"server.PasswordHashResponse","xoredHash":"RV5GX1JVAwADBEVZWwFGTAhZQ1FGX1tYQ11ZVwA\u003d"}YQ11ZVwA\u003d
と読み書き用に同じ方法を使用しcliend。 私はクライアント{"class":"server.PasswordHashRequest","login":"admin"}
から送って、{"class":"server.PasswordHashResponse","xoredHash":"RV5GX1JVAwADBEVZWwFGTAhZQ1FGX1tYQ11ZVwA\u003d"}
と期待しています。 同じコードを使用すると、今すぐ問題が発生し、数分後に問題が発生する可能性があります。 私は知っているものを試しました。私はJavaでsegfaultを取得できましたか?
クライアント側コード:
@Test
public void main() throws Exception {
System.out.println("Opening socket");
InetSocketAddress socketAddress = new InetSocketAddress("localhost", 9090);
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
Selector selector = Selector.open();
socketChannel.register(selector, OP_CONNECT);
socketChannel.connect(socketAddress);
PasswordHashRequest request = new PasswordHashRequest("admin");
System.out.println("Socket open");
while (true) {
System.out.println("Client selector awoken");
selector.select();
for (SelectionKey selectionKey : selector.selectedKeys()) {
if (selectionKey.isConnectable()) {
socketChannel.finishConnect();
selectionKey.interestOps(OP_WRITE);
} else if (selectionKey.isReadable()) {
String response = ServerManager.readMessage((SocketChannel) selectionKey.channel());
System.out.println(response);
server.interrupt();
} else if (selectionKey.isWritable()) {
ServerManager.sendMessage(request, (SocketChannel) selectionKey.channel());
System.out.println("Request sent");
selectionKey.interestOps(OP_READ);
}
}
}
}
サーバー側のコード:
public void run() {
System.out.println("Main thread started");
while (true) {
try {
// Get ready channels
int readyChannels = selector.select();
if (readyChannels == 0) { continue; }
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
// Handle Events
while (keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
// New Client
if (key.isAcceptable()) {
System.out.println("New Client Accepted");
ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
serverSocketChannel.configureBlocking(false);
SocketChannel socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false);
SelectionKey clientKey = socketChannel.register(selector, SelectionKey.OP_READ);
Random randomInt = new Random(System.currentTimeMillis());
clientKey.attach(randomInt.nextInt(Integer.SIZE - 1));
}
// Client has sent data
else if (key.isReadable()) {
handleInput(key);
}
keyIterator.remove();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
読む方法:
public static String readMessage(SocketChannel socketChannel) throws IOException {
ByteBuffer byteBuffer = ByteBuffer.allocate(16);
byteBuffer.clear();
StringBuilder stringBuilder = new StringBuilder();
int bytesRead = socketChannel.read(byteBuffer);
while (bytesRead != -1) {
byteBuffer.flip();
String byteString = new String(byteBuffer.array(), Charset.forName("UTF-8"));
stringBuilder.append(byteString);
byteBuffer.clear();
bytesRead = socketChannel.read(byteBuffer);
}
socketChannel.shutdownInput();
return stringBuilder.toString();
}
Writeメソッド:
public static void writeMessage(String message, SocketChannel channel) throws IOException {
message += "\r\n";
System.out.println(message);
int bufferLength = 16;
byte[] responseBytes = message.getBytes();
int offset = 0;
ByteBuffer buf = ByteBuffer.allocate(bufferLength);
while (responseBytes.length > offset) {
buf.clear();
int div = responseBytes.length - offset;
if (div >= bufferLength) {
buf.put(responseBytes, offset, bufferLength);
} else {
buf.put(responseBytes, offset, div);
}
buf.flip();
channel.write(buf);
offset += bufferLength;
}
channel.shutdownOutput();
}
ありがとう、私は今日それを試してみます。 –