【发布时间】:2016-09-29 22:10:56
【问题描述】:
尽管对这个问题进行了数小时的研究,但我几乎没有取得任何进展。根据我的教授的说法,代码应该可以正常工作......
我有一个保持打开状态的服务器和一个请求文件的客户端。一旦客户端收到文件,客户端就会关闭。
当我打开服务器时,我可以传输一个完整的 .jpg 图像文件。然后客户端关闭,而服务器保持打开状态。我启动另一个客户端并尝试传输相同的图像,并且只有一部分字节被传输/写入磁盘。文件传输仅对服务器传输的第一个文件完全成功!
更奇怪的是,一个简单的 .txt 文本文件从未成功传输。我相信原因在于服务器端,因为它保持打开状态,而不是客户端,每次都重新开始。
服务器代码:
import java.io.*;
import java.net.*;
import java.util.Arrays;
class ft_server {
public static void main(String args[]) throws Exception {
/*
* Asks user for port number and listens on that port
*/
BufferedReader portFromUser = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter the port you'd like to use: ");
int portNumber = Integer.valueOf(portFromUser.readLine());
if (portNumber < 1 || portNumber > 65535) {
System.out.println("Please choose a port number between 1 and 65535.");
return;
}
portFromUser.close();
ServerSocket listenSocket = new ServerSocket(portNumber);
/*
* Finished with user input
*/
/*
* Continuously listens for clients:
*/
while (true) {
Socket clientSocket = listenSocket.accept();
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(clientSocket.getOutputStream());
String clientIP = clientSocket.getRemoteSocketAddress().toString();
System.out.println("The client " + clientIP + " connected!");
String clientMessage = inFromClient.readLine();
System.out.println("The client requested file: " + clientMessage);
// Get file. If doesn't exist, let's client know.
// Otherwise informs client of file size.
File myFile = new File(clientMessage);
if (!myFile.exists()) {
outToClient.writeBytes("File does not exist!\n");
return;
} else {
outToClient.writeBytes(String.valueOf((int)myFile.length()) + "\n");
}
// Create array for storage of file bytes:
byte[] byteArray = new byte[(int)myFile.length()];
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myFile));
// Read file into array:
bis.read(byteArray, 0, byteArray.length);
// Send the file:
outToClient.write(byteArray, 0, byteArray.length);
outToClient.close();
clientSocket.close();
}
}
}
客户代码:
import java.io.*;
import java.net.*;
class ft_client {
public static void main(String args[]) throws Exception {
int byteSize = 2022386;
int bytesRead;
/*
* Asks user for IP and port:
*/
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter an IP address: ");
String ipAddress = inFromUser.readLine();
System.out.println("Enter a port: ");
String port = inFromUser.readLine();
Socket clientSocket;
try {
// Makes socket, port, and calls connect. Assumes it's TCP:
clientSocket = new Socket(ipAddress, Integer.valueOf(port));
} catch (Exception e) {
System.out.println(e.getMessage());
return;
}
// Creates InputStream from server to get file size and other messages:
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
// Anything written to this will be sent to the server:
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
// Asks for a file name to download from the server:
System.out.println("What file do you want?: ");
String message = inFromUser.readLine();
outToServer.writeBytes(message + "\n");
inFromUser.close();
// Listens for confirmation from server.
// If the file exists, the file size is delivered here:
String response = inFromServer.readLine();
System.out.println("File size: " + response);
if (response.equals("File does not exist!")) {
return;
}
// Receives file from server:
byteSize = (int) Integer.valueOf(response);
byte[] byteArray = new byte[byteSize];
InputStream is = clientSocket.getInputStream(); // calling clientSocket.getInputStream() twice???
FileOutputStream fos = new FileOutputStream(message);
BufferedOutputStream bos = new BufferedOutputStream(fos);
// Continuously writes the file to the disk until complete:
int total = 0;
while ((bytesRead = is.read(byteArray)) != -1) {
bos.write(byteArray, 0, bytesRead);
total += bytesRead;
}
bos.close();
System.out.println("File downloaded (" + total + " bytes read)");
clientSocket.close();
}
}
缓冲读取器是否会干扰输出流?有没有更好的文件传输方式?
【问题讨论】:
-
不要在同一个套接字上混合缓冲和非缓冲流和读取器。找到另一种发送文件名的方式,例如使用
DataOutputStream.writeUTF(),并使用DataInputStream.readUTF()阅读。 -
我会试一试的。但是,混合它们有什么本质上的问题吗?
-
缓冲阅读器,错误,缓冲。如果在您读取文件名时它已经存在,它会读取一些图像数据。
-
混合流类型有点糟糕,是的。客户端发送带有
DataOutput.writeBytes(s)的文件名,它发送每个字符的底部字节;然后服务器使用系统的默认字符编码通过 byte->char 转换器 (InputStreamReader) 使用BufferedReader.readLine()读取它。只要你坚持使用纯 ASCII 就可以了,但如果你将 UTF-8 作为默认编码并且文件名中包含非 ASCII 字符,那么一切都会变得非常混乱。 -
@EJP 哦,天哪,我看不到您所说的缓冲区问题!一定要迟到了。不是每次都在服务器循环中重新创建所有 BufferedReader 吗?而且每次都重启客户端....?
标签: java file sockets tcp transfer