将文件传输到java客户端后保持套接字连接打开

将文件传输到java客户端后保持套接字连接打开,java,file,sockets,socketexception,Java,File,Sockets,Socketexception,在学校里,我们有一个项目,我们必须将文件从服务器发送到客户端。问题是,当我们将文件从服务器传输到客户端时,服务器会关闭连接。以下是我们目前的代码: 客户: public static void main(String argv[]) throws Exception { int port = 8888; //default if (argv.length > 0) { port = Integer.parseInt(arg

在学校里,我们有一个项目,我们必须将文件从服务器发送到客户端。问题是,当我们将文件从服务器传输到客户端时,服务器会关闭连接。以下是我们目前的代码:

客户:

    public static void main(String argv[]) throws Exception {

    int port = 8888;  //default
    if (argv.length
            > 0) {
        port = Integer.parseInt(argv[0]);
    }

    Socket clientSocket = new Socket("127.0.0.1", port);
    PrintStream outToServer = new PrintStream(
            clientSocket.getOutputStream());
    BufferedReader inFromServer = new BufferedReader(
            new InputStreamReader(clientSocket.getInputStream()));



    File f = new File("dictionaryPart.txt");

    String serverCommand = inFromServer.readLine().toLowerCase();
    while (serverCommand != null) {
        System.out.println(serverCommand);
        switch (serverCommand) {
            case "velkommen":
                outToServer.println("Hej");
                break;
            case "file":
                f = copy(clientSocket, f);
                String matches = CrackerCentralized.checkFile(f);
                System.out.println(matches);
                outToServer.println(matches);
                break;
        }
        serverCommand = inFromServer.readLine().toLowerCase();
    }
}

public static File copy(Socket clientSocket, File f) {
    try {
        int filesize = 2022386;
        int bytesRead;
        int currentTot = 0;

        byte[] buffer = new byte[filesize];
        InputStream is = clientSocket.getInputStream();
        FileOutputStream fos = new FileOutputStream(f);
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        bytesRead = is.read(buffer, 0, buffer.length);
        currentTot = bytesRead;
        while (bytesRead != -1) {
            bytesRead = is.read(buffer, currentTot, (buffer.length - currentTot));
            if (bytesRead >= 0) {
                currentTot += bytesRead;
            }
        }
        bos.write(buffer, 0, currentTot);
        bos.flush();
        bos.close();
    } catch (IOException ex) {
        Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
    }
    return f;
}
服务器:

    try {
        PrintStream outToClient = new PrintStream(connection.getOutputStream());
        OutputStream os = connection.getOutputStream();
        BufferedInputStream input = new BufferedInputStream(new FileInputStream(f));
        outToClient.println("file");
        final byte[] buffer = new byte[(int) f.length()];
        input.read(buffer, 0, buffer.length);
        os.write(buffer, 0, buffer.length);
        os.write(-1);
        os.flush();
        System.out.println(connection.isClosed());
        os.close();
        System.out.println(connection.isClosed());
    } catch (IOException ex) {
        Logger.getLogger(SocketController.class.getName()).log(Level.SEVERE, null, ex);
    }
我知道为什么连接一直关闭。我们通过写入来关闭套接字的输出

output.close();
但是我不知道我们必须以什么其他方式尝试这样做,以使服务器继续侦听客户端的答案(匹配/不匹配),以便服务器知道它是否应该发送更多文件,或者客户端是否成功。。甚至可以在不关闭与服务器的连接的情况下发送at文件吗?过去两天我在谷歌上搜索了一整天,一点运气都没有


谢谢你的阅读和帮助

为了实现您的要求,您需要建立一个服务器和客户端都能理解的通信协议。需要传输的内容包括“我开始向您发送信息”和“我已完成发送内容”的内容。可能还有更多内容,例如信息定界(例如Mime多部分表单边界)。但至少,您需要启动和停止令牌。
在此基础上展开:以最简单的形式查看代码:
server:loop{write()}->client:loop{read()}
。关闭服务器端的流会向客户端发送-1值,该值通常作为停止信号使用。如果您希望无限期地维护连接,并在不同的时间向客户机写入数据,则必须发送一些内容,说明“此事务已完成”。以下是伪ish代码——手绘,未编译

// SERVER
private Socket socket; // initialized somewhere

private static final byte[] STOP = "</COMMS>".getBytes();

public void sendData(byte[] bytes) throws IOException{

  OutputStream out = socket.getOutputStream();

  if(bytes != null){
      out.write(bytes,0,bytes.length);
  }

  out.write(STOP);
}  // notice we exit the method without closing the stream.
//服务器
专用套接字;//在某处初始化
私有静态最终字节[]STOP=“.getBytes();
公共void sendData(字节[]字节)引发IOException{
OutputStream out=socket.getOutputStream();
如果(字节数!=null){
out.write(字节、0、字节、长度);
}
写出(停止);
}//注意,我们在不关闭流的情况下退出了该方法。

//客户端
专用套接字;//在某处初始化
私有静态最终字节[]STOP=“.getBytes();

private static final int BUFFER_SIZE=1024感谢madConan的回复,它给了我一个很好的方法。我将在这里发布我的代码,以便其他人将来可以使用它

服务器代码

    public void run() {
    try {
        PrintStream outToClient = new PrintStream(connection.getOutputStream());
        OutputStream os = connection.getOutputStream();
        BufferedInputStream input = new BufferedInputStream(new FileInputStream(f));
        outToClient.println("file");
        copy(input, os, f);
        System.out.println(connection.isClosed());
    } catch (IOException ex) {
        Logger.getLogger(SocketController.class.getName()).log(Level.SEVERE, null, ex);
    }
}

private static void copy(final InputStream is, final OutputStream os, File f) throws         IOException {
    final byte[] stop = "stop".getBytes();
    final byte[] buffer = new byte[(int) f.length()];
    is.read(buffer, 0, buffer.length);
    os.write(buffer, 0, buffer.length);
    os.write(stop);
    os.flush();
}
客户端代码

    public static File recieveData(Socket clientSocket, File f) {
    try {
        InputStream in = clientSocket.getInputStream();
        FileOutputStream output = new FileOutputStream(f);
        byte[] content;
        byte[] bytes = new byte[1024 << 8];
        int bytesRead;
        while (true) {
            if (recieveStop(f)) {
                removeStop(f);
                break;
            }
            bytesRead = in.read(bytes);
            output.write(bytes, 0, bytesRead);
        }
    } catch (IOException ex) {
        Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
    }
    return f;
}

public static boolean recieveStop(File f) {
    BufferedReader br = null;
    try {
        br = new BufferedReader(new FileReader(f));
        String currentLine;
        String lastLine = "";
            while ((currentLine = br.readLine()) != null) {
                lastLine = currentLine;
            } 
        if (lastLine.equals("stop")) {
            return true;
        }
    } catch (FileNotFoundException ex) {
        Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IOException ex) {
            Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
        try {
            br.close();
        } catch (IOException ex) {
            Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    return false;
}

public static void removeStop(File f) {
    try {
        RandomAccessFile raFile = new RandomAccessFile(f, "rw");
        long length = raFile.length();
        raFile.setLength(length - 4);
        raFile.close();
    } catch (FileNotFoundException ex) {
        Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IOException ex) {
        Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
    }

}
公共静态文件receiveData(套接字客户端套接字,文件f){
试一试{
InputStream in=clientSocket.getInputStream();
FileOutputStream输出=新的FileOutputStream(f);
字节[]内容;

字节[]字节=新字节[1024我不知道这是否太多,但你能提供一个如何实现这一点的示例,或者告诉我更多关于它的信息吗?我对套接字编程非常陌生,我不确定我是否理解你的意思。+1用于建立应用程序协议的需要。分隔符不是协议中框显消息的唯一方法,你也可以简单地为正在传输的消息的长度添加前缀,以便接收方知道要读取多少字节。有一件事:您可能不知道使用“stop”作为令牌的内容,除非您确实确定有效负载永远不会包含“stop”.哦,是的,谢谢你,我没有真的考虑过它…它有时可能不包含它..嘿,乌尔博…不确定你是否会记住这一点,但你是如何让你的循环实际中断的?我的循环只是冻结,似乎没有达到中断点。嗨@Visionwriter。我所做的是使用停止信号。在这种情况下,我使用了“停止”正如MadConan指出的那样,信号不是最好的主意,除非你绝对确定你的有效载荷中没有这个词。谢谢,伙计。终于弄明白了。我没有阅读文本,所以我不能使用readLine。最后在读取空缓冲区之前,使用文件大小作为测试,它工作了。不过,谢谢。
    public static File recieveData(Socket clientSocket, File f) {
    try {
        InputStream in = clientSocket.getInputStream();
        FileOutputStream output = new FileOutputStream(f);
        byte[] content;
        byte[] bytes = new byte[1024 << 8];
        int bytesRead;
        while (true) {
            if (recieveStop(f)) {
                removeStop(f);
                break;
            }
            bytesRead = in.read(bytes);
            output.write(bytes, 0, bytesRead);
        }
    } catch (IOException ex) {
        Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
    }
    return f;
}

public static boolean recieveStop(File f) {
    BufferedReader br = null;
    try {
        br = new BufferedReader(new FileReader(f));
        String currentLine;
        String lastLine = "";
            while ((currentLine = br.readLine()) != null) {
                lastLine = currentLine;
            } 
        if (lastLine.equals("stop")) {
            return true;
        }
    } catch (FileNotFoundException ex) {
        Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IOException ex) {
            Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
        try {
            br.close();
        } catch (IOException ex) {
            Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    return false;
}

public static void removeStop(File f) {
    try {
        RandomAccessFile raFile = new RandomAccessFile(f, "rw");
        long length = raFile.length();
        raFile.setLength(length - 4);
        raFile.close();
    } catch (FileNotFoundException ex) {
        Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IOException ex) {
        Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
    }

}