【发布时间】:2017-04-06 14:08:45
【问题描述】:
我正在尝试通过 Java 中的套接字传输文件,我目前对服务器的方法是:
- 创建新线程
- 线程使用 dos.writeUTF() 发送文件名
- 线程使用 dos.writeLong() 发送文件大小
- 线程使用 dos.write() 发送文件
每个线程代表一个客户端,dos 是 DataOutputStream 的一个实例。
现在,在客户端上我正在做同样的事情,但阅读而不是写作:
- 使用 dis.readUTF() 读取文件名
- 使用 dis.readLong() 读取文件大小
- 使用 dis.read() 读取文件
其中 dis 是 DataInputStream 的一个实例。
问题是:发送一个文件时,一切正常,但是当我尝试一个接一个地发送 3 个文件时,看起来服务器正在按预期将所有内容正确写入流,但客户端(在第一个文件之后,意味着这从第二个文件开始发生)卡在 dis.readUTF() 上并且无法继续。
我已经尝试修复此问题好几天了,但无法正常工作。
以下是源代码:
服务器:
Main.java
public class Main {
public static void main(String[] args) {
boolean boolDebug = true;//TODO REMOVE THIS!!
ServerSocket serverSock = null;
List<Socket> clientSocks;
List<ClientThread> clientThreads;
try {
serverSock = new ServerSocket(9090);
} catch(Exception e){
e.printStackTrace();
}
clientSocks = new ArrayList<>();
clientThreads = new ArrayList<>();
ServerSocket finalServerSock = serverSock;
System.out.println();
System.out.println("Listening for incoming connections\n");
new Thread(){
@Override
public void run() {
super.run();
while (true) {
try {
Socket newSock = finalServerSock.accept();
clientSocks.add(newSock); //FIXME Remove sockets when closed
Thread thread = new ClientThread(newSock, usr, psw);
thread.start();
clientThreads.add((ClientThread)thread);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}.start();
}
}
ClientThread.java
public class ClientThread extends Thread {
private Socket socket;
private DataInputStream inStream;
private DataOutputStream outStream;
private String dbUser;
private String dbPassword;
public ClientThread(Socket socket, String DbUser, String DbPass) {
this.socket = socket;
this.dbUser = DbUser;
this.dbPassword = DbPass;
}
@Override
public void run() {
try {
inStream = new DataInputStream(socket.getInputStream());
outStream = new DataOutputStream(socket.getOutputStream());
sendFile("a.txt");
sendFile("b.txt");
sendFile("c.txt");
} catch (Exception e) {
e.printStackTrace();
}
}
void sendFile(String file){
try {
File f = new File(file);
outStream.writeUTF(file);
outStream.writeLong(f.length());
FileInputStream fis = new FileInputStream(f);
byte[] buffer = new byte[4096];
while (fis.read(buffer) > 0) {
outStream.write(buffer);
}
fis.close();
}catch(Exception e){
e.printStackTrace();
}
}
int getSize(byte[] buffer,long remaining){
try {
return Math.toIntExact(Math.min(((long) buffer.length), remaining));
}catch(ArithmeticException e){
return 4096;
}
}
}
客户: 主.java
class Main {
static int getSize(byte[] buffer, long remaining) {
try {
return Math.toIntExact(Math.min(((long) buffer.length), remaining));
} catch (ArithmeticException e) {
return 4096;
}
}
static void saveFile(Socket clientSock,DataInputStream dis) throws IOException {
String fileName = dis.readUTF();
File f = new File(fileName);
FileOutputStream fos = new FileOutputStream(f);
byte[] buffer = new byte[4096];
long filesize = dis.readLong();
int read = 0;
int totalRead = 0;
long remaining = filesize;
while ((read = dis.read(buffer, 0, getSize(buffer, remaining))) > 0) {
totalRead += read;
remaining -= read;
System.out.println("read " + totalRead + " bytes.");
fos.write(buffer, 0, read);
}
fos.close();
}
public static void main(String[] args) throws Exception {
Socket sock = new Socket("192.168.2.17", 9090);
DataInputStream dis = new DataInputStream(sock.getInputStream());
saveFile(sock,dis);
saveFile(sock,dis);
saveFile(sock,dis);
}
}
非常感谢,期待解决这个问题:(
【问题讨论】:
-
读取utf,长文件字节?
-
忽略,我看错了。等等,不,我没有。您至少有一个循环,您可以在其中不断写入完整缓冲区而不是读取量。在您的
sendFile方法中。 -
我明白了,有什么办法可以解决吗?
-
是的,阅读 IO 教程并停止编写损坏的代码。为什么在其他部分你已经正确地完成了它,但是在那个特定的循环中你忽略了返回值?事实上,你的其他循环看起来也很混乱。给你,I/O Trail。
标签: java multithreading sockets client-server data-transfer