我的计划基本上是:
客户端向服务器发送字符串,
基于此String,Server正在创建一个ArrayList,
将ArrayList发送回客户端。
这里失败的是:
客户端发送字符串后,服务器会收到它,并且不会执行任何其他操作。在这段时间内,客户端继续工作并获得NullPointer。
客户端:
public static ArrayList<String> sendStringToServer(String report) {
Socket socket;
ArrayList<String> fieldsList = new ArrayList<String>();
try {
socket = new Socket("localhost", 2345);
OutputStream os = socket.getOutputStream();
PrintStream ps = new PrintStream(os, true);
ps.println(report);
ps.flush();
//Here the debugger should stop and wait for server to create a List
//at this point there is no answer, code breaks
ObjectInputStream objectInput = new ObjectInputStream(socket.getInputStream());
Object object = objectInput.readObject();
fieldsList = (ArrayList<String>) object;
socket.close();
return fieldsList;
} catch (IOException e1) {
e1.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
服务器端:
public class Server {
private ServerSocket serverSocket;
private Socket clientSocket;
private String telegram;
private StringBuilder telegramSB;
public static void main(String[] args) throws IOException, JRException {
new Server();
}
public Server() {
try {
serverSocket = new ServerSocket(2345);
while (true) {
clientSocket = serverSocket.accept();
InputStream is = clientSocket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
try {
//debugger goes to here and then stops
telegram = br.readLine();
int counter = 0;
boolean startSeq = false;
for (char ch : telegram.toCharArray()) {
if (counter == 0 && ch == '/') {
startSeq = true;
}
if (startSeq == true) {
telegramSB = new StringBuilder();
telegramSB.append(ch);
}
if (ch == '\n') {
if (telegram.length() < 255) {
sendListWithFields();
} else {
new Launcher(telegram).run();
}
}
counter++;
}
} catch (JRException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
System.out.println(e);
}
}
答案 0 :(得分:0)
我的猜测是,BufferedReader正在等待填充缓冲区并且您还没有发送足够的数据来执行此操作并返回,以便等待更多数据通过,从而不会(因为您的客户端)停止写作并开始阅读)。您可以通过将更多数据加载到客户端的OutputStream中并将其刷新来暂时测试此理论。
如果出现以上情况,那么您可能不想使用BufferedReader,但此处还有其他问题,这也意味着您可能希望避免使用PrintStream和BufferedReader进行通信和序列化。例如,两台不同机器和JVM上的默认字符编码可能不同。当您创建PrintStream和InputStreamReader时,您没有指定字符编码,因此它们可能最终不匹配,并且您编写的字符串(包括换行符)可能最终被远程端完全区分,这可能也是它阻塞的原因(客户端以一种方式编码换行符,但服务器期望它以完全不同的方式编码),尽管我认为不太可能。
如果您没有 使用PrintStream,那么我建议改为使用DataOutputStream / DataInputStream:
//Client
BufferedOutputStream bufout = new BufferedOutputStream(socket.getOutputStream());
DataOutputStream dout = new DataOutputStream(bufout);
dout.writeUTF(report);
dout.flush();
//Server
BufferedInputStream bufin = new BufferedInputStream(socket.getInputStream());
DataInputStream din = new DataInputStream(bufin);
String report = din.readUTF();
你仍然可以从BufferedIn / OutputStreams缓冲,所以它将是高性能的,但DataIn / OutputStreams将为你管理可变长度对象的终止 - 它们将发送一个长度前缀字符串,以告诉另一方到底有多少字节阅读,所以你不需要使用特殊字符来终止你写的字符串,这也意味着你的字符串内容并不重要。在上面的示例中,即使它的字符串中有换行符,它也会正常工作,服务器会读取直到第一个换行符,而不是你发送的字符串的结尾,这会使它们在下一次发送时不同步/沿着那条小溪接收。
使用write / readUTF还指定了编码(UTF-8),因此也没有不匹配。