我刚刚开始学习java。我修改了服务器/客户端通信程序的客户端代码,为客户端创建了两个线程,用于接收用户输入的主线程,以及用于接收服务器响应的inputThread。我确信服务器已将响应发送到客户端,但是,客户端没有获得响应消息。
这是我的代码。任何人都可以帮我搞清楚吗?感谢
package clientnio;
import java.net.*;
import java.nio.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Scanner;
public class ClientNIO {
public static int bufferLen = 50;
public static SocketChannel client;
public static ByteBuffer writeBuffer;
public static ByteBuffer readBuffer;
public static void main(String[] args) {
writeBuffer = ByteBuffer.allocate(bufferLen);
readBuffer = ByteBuffer.allocate(bufferLen);
try {
SocketAddress address = new InetSocketAddress("localhost",5505);
System.out.println("Local address: "+ address);
client=SocketChannel.open(address);
client.configureBlocking(false);
//readBuffer.flip();
new inputThread(readBuffer);
/*
String a="asdasdasdasddffasfas";
writeBuffer.put(a.getBytes());
writeBuffer.clear();
int d=client.write(writeBuffer);
writeBuffer.flip();
*/
while (true) {
InputStream inStream = System.in;
Scanner scan = new Scanner(inStream);
if (scan.hasNext()==true) {
String inputLine = scan.nextLine();
writeBuffer.put(inputLine.getBytes());
//writeBuffer.clear();
System.out.println(writeBuffer.remaining());
client.write(writeBuffer);
System.out.println("Sending data: "+new String(writeBuffer.array()));
writeBuffer.flip();
Thread.sleep(300);
}
}
}
catch(Exception e) {
System.out.println(e);
}
}
}
class inputThread extends Thread {
private ByteBuffer readBuffer;
public inputThread(ByteBuffer readBuffer1) {
System.out.println("Receiving thread starts.");
this.readBuffer = readBuffer1;
start();
}
@Override
public void run() {
try {
while (true) {
readBuffer.flip();
int i=ClientNIO.client.read(readBuffer);
if(i>0) {
byte[] b=readBuffer.array();
System.out.println("Receiving data: "+new String(b));
//client.close();
//System.out.println("Connection closed.");
//break;
}
Thread.sleep(100);
}
}
catch (Exception e) {
System.out.println(e);
}
}
}
答案 0 :(得分:1)
在读取之前在缓冲区上调用flip()
是错误的。不要那样做。您需要在+写入+之前将其翻转,或从中获取,然后再compact()
。
答案 1 :(得分:-1)
免责声明:我不是Java的活跃用户。 (我只在学校使用它。)
建议:如果您使用阻止模式,我认为这将大大简化调试过程,至少在您的代码示例正常工作之前。 (目前您的代码似乎没有受益于非阻塞模式。)
我发现了两个问题,最终导致可能需要更改的四行代码:
ByteBuffer
分配其后备阵列时,它通过将position
设置为零并将limit
设置为该阵列的容量来设置自己准备写入。你对ByteBuffer.flip()
的两种用法(分别在写循环和阅读循环中)似乎与惯例相悖。ByteBuffer.array()
方法始终返回整个后备数组,因此它的大小始终为bufferLen
。因此,从全尺寸数组构造的String
可能包含来自先前传输的垃圾。
String
和字节数组之间的转换必须使用与服务器相同的编码。我对第一期的建议更改:
(注意:我不知道如何修复数组修剪和编码问题。)
writeBuffer.put(inputLine.getBytes());
writeBuffer.flip(); // <--here
client.write(writeBuffer);
...
writeBuffer.clear(); // <-- should be clear() instead of flip()
Thread.sleep(300);
// readBuffer.flip(); // <-- remove this line
int i=ClientNIO.client.read(readBuffer);
if(i>0) {
readBuffer.flip(); // <-- move it here
byte[] b=readBuffer.array();
System.out.println("Receiving data: "+new String(b));
...
}
参考