客户端-服务器Java程序在运行时使用套接字,但在解除bug时工作
我创建了一个简单的实用程序,它实现了服务器和客户端。服务器等待输入连接,客户端连接,若服务器上的文件夹中有任何文件,它们将发送到客户端。 我使用DataInput/OutputStreams-writeUTF/readUTF在客户端和服务器之间发送消息,writeLong/readLong-发送文件大小,write/read发送数据。 问题是,当我在发送一两个文件后同时运行客户端和服务器工作模式时。但是,如果我在IDE中一步一步地跟踪客户机和服务器,它会工作得很好,如果我传输缓冲区大小为一个字节的文件,它也会工作——因此它工作得很慢,但不会卡住。 我在客户端使用EclipseIDE,JDK1.7在服务器端使用1.8,在VMWare播放器的两个实例上也尝试了1.7,Ubuntu linux和Windows2003服务器。 我还尝试添加Thread.sleep10000和flush任何可能被刷新的东西,甚至添加了socket.setTcpNoDelaytrue;但没有结果。 看起来服务器发送下一个文件名并等待来自客户机的回音,但客户机并没有得到它并锁定readUTF。但是,如果我在手动模式下一步一步地做,它工作得很好。 有什么想法吗?谢谢大家! 客户资料来源:客户端-服务器Java程序在运行时使用套接字,但在解除bug时工作,java,sockets,datainputstream,dataoutputstream,Java,Sockets,Datainputstream,Dataoutputstream,我创建了一个简单的实用程序,它实现了服务器和客户端。服务器等待输入连接,客户端连接,若服务器上的文件夹中有任何文件,它们将发送到客户端。 我使用DataInput/OutputStreams-writeUTF/readUTF在客户端和服务器之间发送消息,writeLong/readLong-发送文件大小,write/read发送数据。 问题是,当我在发送一两个文件后同时运行客户端和服务器工作模式时。但是,如果我在IDE中一步一步地跟踪客户机和服务器,它会工作得很好,如果我传输缓冲区大小为一个字节
/**
* Method receives a file from server
* @param outWriter
* @param inBufferedReader
* @param inStream
*
*/
private void receiveFileFromServer(DataOutputStream out, DataInputStream in) {
try {
String fileName = in.readUTF(); ///<----- stucks here *************
if (awlConnectionLogger.isInfoEnabled()) {
awlConnectionLogger.info("Receiving file "+fileName);
}
out.writeUTF(fileName);
out.flush();
Long fileSize = in.readLong();
if (awlConnectionLogger.isInfoEnabled()) {
awlConnectionLogger.info("Filesize "+fileSize);
}
out.writeUTF(fileSize.toString());
out.flush();
File localFile = new File(fileName);
FileOutputStream fileOS = new FileOutputStream(localFile);
byte[] buffer = new byte [2048];
int bytesRead = 0;
try {
for (int i = 0; i<fileSize/buffer.length; i++) {
bytesRead = in.read(buffer, 0, buffer.length);
fileOS.write(buffer,0, bytesRead);
}
bytesRead = in.read(buffer, 0, (int)(fileSize%buffer.length));
fileOS.write(buffer,0, bytesRead);
System.out.println("----------------------- "+bytesRead);
} catch (IOException e) {
awlConnectionLogger.error("Error reading file "+fileName);
};
fileOS.close();
if (awlConnectionLogger.isInfoEnabled()) {
awlConnectionLogger.info("File received.");
}
} catch (IOException e) {
awlConnectionLogger.error("Error reading Stream or socket closed");
}
}
/**
* Method sends a @param command to server, waits for answer, then if answer is not null and equals @param answer it logs @param messageOk else @param messageError
* returns true if everything is ok, else returns false
* @param outWriter
* @param inBufferedReader
* @throws IOException
*/
private boolean sendCommandReceiveAnswer(String command, String answer, String messageOk,String messageError,
DataOutputStream out, DataInputStream in) throws IOException {
out.writeUTF(command); //Hello handshake
out.flush();
String data = in.readUTF();
if ((data!=null)&&(data.equals(answer))) {
if (awlConnectionLogger.isInfoEnabled()) {
awlConnectionLogger.info(messageOk);
}
return true;
} else {
awlConnectionLogger.error(messageError);
return false;
}
}
/**
* Try to establish connection with the awl-server according to detected RDP session
* @param serverIP - ip address of server
* @param user - username
*/
private void establishConnection(String serverIP, String user) {
if (awlConnectionLogger.isInfoEnabled()) {
awlConnectionLogger.info("Trying to establish awl-connection to "+serverIP+" as "+user);
}
Integer remoteAwlPort = Integer.parseInt(Config.awlPort);
try (Socket awlServerSocket = new Socket(serverIP,remoteAwlPort)) {//Creating autocloseable socket
this.awlServerSocket = awlServerSocket;
DataOutputStream out = new DataOutputStream(awlServerSocket.getOutputStream());
DataInputStream in = new DataInputStream(awlServerSocket.getInputStream());
if (!sendCommandReceiveAnswer("Hello-awl-client", "Hello-awl-server", "Server hello OK.",
"Unknown server type. Closing thread.", out, in)) {
return;
}; //Hello handshake - return if not successful
if (!sendCommandReceiveAnswer(user, "User-ok", "Username sent.", "Error sending username. Closing thread.", out, in)) {
return;
} //Sending username
String hostName = InetAddress.getLocalHost().getHostName(); //Getting client local hostname
if (!sendCommandReceiveAnswer(hostName, "Hostname-ok", "Local hostname "+hostName+" sent. Ready to receive files.",
"Error sending hostname. Closing thread.", out, in)) {
return;
} //Sending hostname
awlServerSocket.setTcpNoDelay(true);
while (isActive) {
receiveFileFromServer(out, in); //receiving files
out.writeUTF("Ready");
out.flush();
}
} catch (UnknownHostException e) {
awlConnectionLogger.error("Error in server IP adress");
} catch (SocketException e) {
awlConnectionLogger.error("Problem accessing or creating Socket.");
} catch (IOException e) {
awlConnectionLogger.error("General IO Error or Socket closed");
};
}
服务器源:
void Echo (DataInputStream in) {
String echo = null;
try {
echo = in.readUTF();
System.out.println("Echo:"+echo);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void sendToClient (File file, DataOutputStream out, DataInputStream in) {
System.out.println("Sending file name "+file.getName());
try {
out.writeUTF(file.getName());
out.flush();
Echo (in); //<--------- stucks here *******************
out.writeLong(file.length());
out.flush();
Echo (in);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Sending file");
byte [] buffer = new byte [2048];
FileInputStream fileIS = null;
try {
fileIS = new FileInputStream(file);
} catch (FileNotFoundException e) {
System.out.println("Error opening file "+file);
e.printStackTrace();
}
try {
Integer bytesRead;
int i = 0;
while((bytesRead=fileIS.read(buffer))>0) {
out.write(buffer, 0, bytesRead);
}
out.flush();
} catch (IOException e) {
System.out.println("Error reading file "+file);
e.printStackTrace();
};
System.out.println("File sent.");
try {
fileIS.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run () {
DataOutputStream out = null;
DataInputStream in = null;
String data = null;
String user = null;
String clientHostName = null;
try {
socket.setTcpNoDelay(true);
out = new DataOutputStream(socket.getOutputStream());
in = new DataInputStream(socket.getInputStream());
} catch (IOException e1) {
e1.printStackTrace();
}
System.out.println("New incoming connection thread starded.");
try {
data = in.readUTF();
if (data.equals("Hello-awl-client")) {
System.out.println("Client hello OK.");
out.writeUTF("Hello-awl-server");
out.flush();
user = in.readUTF();
System.out.println("User: "+user);
out.writeUTF("User-ok");
out.flush();
clientHostName = in.readUTF();
System.out.println("Client hostname: "+clientHostName);
System.out.println("Server hostname: "+InetAddress.getLocalHost().getHostName());
out.writeUTF("Hostname-ok");
out.flush();
System.out.println("Ready to send files.");
while (isActive) {
File file = new File(ServerConfig.pdfFolder+"//"+user);
if (!file.isDirectory()) {
System.out.println("Error in path to user directory. Exiting thread");
return;
}
File [] files = file.listFiles();
for (File fileItem:files) {
while (!fileItem.renameTo(fileItem)) {
Thread.sleep(1000);
}; //waits while file is not busy to send it
if (socket.isOutputShutdown()) {
out = new DataOutputStream(socket.getOutputStream());
}
sendToClient (fileItem, out, in);
if (fileItem.delete()) {
System.out.println("File deleted.");
} else {
System.out.println("File not deleted.");
}
data = in.readUTF();
System.out.println(data);
}
}
} else {
System.out.println("Unknown connection type. Closing thread.");
return;
}
} catch (IOException | InterruptedException e) {
System.out.println("Connection error or can't sleep thread. Closing thread.");
return;
}
}
您能在客户端上打印出读取循环中的实际字节读取吗?不仅仅是读取提醒的部分?是的,我这样做了,它等于缓冲区大小。我认为这也有问题,但没有。循环客户端从不检查字节读取,字节读取可以是0到缓冲区长度。改用,或者用while循环替换for循环,并实际使用返回的bytesRead。@vanOekel,非常感谢。我花了两周的时间研究这个问题——看起来你关于readFully的建议非常完美!再次感谢你!