我有一个运行它时SOMETIMES挂起的java代码。它是一个put命令,它通过套接字(以及输入流等文件从服务器到客户端)。有时它可以工作,但有时它没有,我得到一个错误信息。我尝试了所有可能通过调试的路径,我永远不会让它挂起。有没有办法在日食中检查它?
if (sentence.length() > 3 && sentence.substring(0, 3).equals("put")) {
File checkFile = new File(dir.getCurrentPath(), sentence.substring(4));
if (checkFile.isFile() && checkFile.exists()) {
try {
outToServer.writeBytes(sentence + "\n");
boolean cont = false;
String x;
while (!cont) {
if ((x = inFromServer.readLine()).equals("continue")) {
cont = true;
}
}
String name = sentence.substring(4);
copy.copyFile(name);
// outToServer.writeBytes("continue" + "\n");
这是接收PUT请求的客户端代码(即put test.txt接受文件test.txt并将其放入服务器的本地目录。
复制文件:(复制数据的东西)
File checkFile = new File(dir.getCurrentPath(), file);
if (checkFile.isFile() && checkFile.exists()) {
DataOutputStream outToClient = new DataOutputStream(socket.getOutputStream());
// byte[] receivedData = new byte[8192];
File inputFile = new File(dir.getCurrentPath(), file);
byte[] receivedData = new byte[(int) inputFile.length()];
// String theLength = "" + inputFile.length();
outToClient.writeBytes("" + inputFile.length() + "\n");
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(getCopyPath(file)));
// if (extension.equals("")) {
// extension = "txt";
// }
// BufferedReader inFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// boolean cont = false;
// while (!cont) {
// if (inFromClient.readLine().equals("continue")) {
// cont = true;
//
// }
// }
// outToClient.writeBytes("continue" + "\n");
bis.read(receivedData, 0, receivedData.length);
OutputStream os = socket.getOutputStream();
os.write(receivedData, 0, receivedData.length);
// outToClient.writeBytes("finish" + "\n");
os.flush();
服务器上的协议(复制文件中的内容)
if (get.equals("put")) {
//so the client sends: the put request
//then sends the length
try {
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(socket.getOutputStream());
outToClient.writeBytes("continue" + "\n");
int length = Integer.parseInt(inFromClient.readLine());
// String x = "";
// boolean cont = false;
// while (!cont) {
// String temp = inFromClient.readLine();
// if (temp.equals("finish")) {
// cont = true;
// }
// else {
// x += temp;
// }
// }
byte[] recieveFile = new byte[length];
InputStream is = socket.getInputStream();
FileOutputStream fos = new FileOutputStream("Copy " + input.substring(4));
BufferedOutputStream bos = new BufferedOutputStream(fos);
int bytesRead;
int current = 0;
bytesRead = is.read(recieveFile, 0, recieveFile.length);
current = bytesRead;
如果你不能回答具体的问题,请告诉我如何调试挂起的代码或如何调试并发代码。(顺便说一下,传递信号的方式是通过传递令牌,你可以看,即服务器发出一个继续令牌,告诉客户端开始发送数据,我没有通过线程方法通知和等待,因为我无法使用,因为任何单个对象只有1个方法。
答案 0 :(得分:2)
当您的进程挂起时,获取进程的当前堆栈转储。这将告诉你为什么这个过程被挂起了。
请注意,您的程序中至少有一个错误,因为您没有处理InputStream.read()
方法的返回值,这至少会导致您在服务器端丢失数据。 (有关详细信息,请参阅@ rk2010的答案)。
相反,您应该独占使用DataOutputStream / DataInputStream。将长度写为长值(即DataOutputStream.writeLong(long)
),然后写入后的字节(即DataOutputStream.write(byte[])
)。然后使用DataInputStream中的相应方法读取数据。因为您可以在读取时专门使用DataInputStream(首先读取文件大小然后读取实际文件字节),所以在切换读取“模式”时不会有丢失字节的风险(此外,DataInputStream 不> em>执行任何内部缓冲,如BufferedReader)。不要使用读者/作者。
答案 1 :(得分:0)
在每次读写命令后添加日志记录。为每个线程命名。 运行程序,看看日志如何与你期望的一致。
请注意,您不能总是像您一样依赖读取方法。安全的阅读方式是循环,直到你得到一个负长度。
int len = -1;
byte[] buff = new byte[1024]; // for 4KB, use: 4* 1024
while ( (len = is.read(buff, 0, buff.length)) > -1){
// copy len number of bytes from buff array into some other place.
}
查看IOUtils.copy方法 from Apache Commons IOUtils class