【问题标题】:Java socket is stuck on readUTF()Java 套接字卡在 readUTF() 上
【发布时间】:2017-04-06 14:08:45
【问题描述】:

我正在尝试通过 Java 中的套接字传输文件,我目前对服务器的方法是:

  1. 创建新线程
  2. 线程使用 dos.writeUTF() 发送文件名
  3. 线程使用 dos.writeLong() 发送文件大小
  4. 线程使用 dos.write() 发送文件

每个线程代表一个客户端,dos 是 DataOutputStream 的一个实例。

现在,在客户端上我正在做同样的事情,但阅读而不是写作:

  1. 使用 dis.readUTF() 读取文件名
  2. 使用 dis.readLong() 读取文件大小
  3. 使用 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


【解决方案1】:

通过更改修复

while (fis.read(buffer) > 0) {
    outStream.write(buffer);
}

int count;
while ((count = fis.read(buffer)) > 0) {
    outStream.write(buffer, 0, count);
}

在服务器端的ClientThread.java中

【讨论】:

    猜你喜欢
    • 2020-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多