1

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

客户:

    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();

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

感谢您的阅读和您的帮助。

4

2 回答 2

2

为了实现您所要求的,您需要建立服务器和客户端理解的通信协议。需要传输一些内容,例如“我开始向您发送信息”,以及“我已经完成发送内容”的内容。可能还有更多——例如信息定界(例如,Mime 多部分表单边界)。但至少,您需要开始和停止标记。


对此进行扩展:以最简单的形式查看代码: server:loop{write()} -> client:loop{read()}. 在服务器端关闭流向客户端发送 -1 值,通常作为停止信号使用。如果您想无限期地保持连接,并在不同时间写入客户端,则必须发送“此事务已完成”的内容。以下是伪代码——手绘,未编译。

// 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.

// CLIENT
private Socket socket; // initialized somewhere
private static final byte[] STOP = "</COMMS>".getBytes();
private static final int BUFFER_SIZE = 1024 << 8;
private InputStream in;

public byte[] receiveData(){
    if(in == null){
      in = socket.getInputStream();
    }
    byte[] content;
    byte[] bytes = new byte[BUFFER_SIZE];
    int bytesRead;
    while((bytesRead = in.read(bytes)) != -1){  // normal termination
          if(receivedStop(bytes,bytesRead)){  // see if stopped
               removeStopBytes(bytes,bytesRead); // get rid of the STOP bytes
               content = buildContent(content,bytes,bytesRead); // transfer bytes to array
               break;
          }
          content = buildContent(content,bytes,bytesRead); // transfer bytes to array
    }
    return content;
}

同样,这是徒手画的,没有编译或测试。我敢肯定这并不完全正确,但希望你能明白要点。服务器写入内容但从不关闭流。客户端读取流以寻找 STOP 内容,构建最终内容,直到到达停止。

于 2013-10-29T15:13:36.477 回答
1

感谢 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);
    }

}

希望这会帮助其他有同样问题的人。

于 2013-10-30T06:39:46.377 回答