Java IO 服务器客户端读取并处理用户输入

Java IO Server Client read and process users input

我有一个简单的文件服务器和客户端(来自网络的代码),可以让我将文件发送到我家庭局域网内的另一台笔记本电脑。现在,从服务器发送到客户端的文件是硬编码的,但我想提示客户端的用户输入文件名,将其发送到服务器并发回指定的文件。我的代码如下所示:

服务器

import java.net.*;
import java.io.*;

public class Server {  

    public static void main(String[] args) {

        BufferedOutputStream outputStream;
        BufferedInputStream inputStream;
        FileInputStream fileInput;

        String file = "C:/java/file.mp4";

        try {

            ServerSocket socket = new ServerSocket(12345); 

            while(true) { 

                Socket clientSocket = socket.accept();

                outputStream = new BufferedOutputStream(clientSocket.getOutputStream());

                fileInput = new FileInputStream(file);

                inputStream = new BufferedInputStream(fileInput);

                int packetToSend = -1;

                byte[] buffer = new byte[8192];

                while((packetToSend = inputStream.read(buffer)) > -1) { 

                    outputStream.write(buffer, 0, packetToSend);
                    System.out.println("sending " + packetToSend + " bytes");
                    outputStream.flush();

                }

            }

        }

        catch(Exception e) {

            e.printStackTrace();

        }

    }

}

这就是客户端代码(服务器的IP地址是参数s[0],保存文件的路径是main方法中的s[1]。

import java.net.*;
import java.io.*;

public class Client {

    public static void main(String[] s) {

        try { 

            String address = new String(s[0]);
            String fileToSave = new String(s[1]); 
            Socket socket = new Socket(address,12345);

            BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());

            BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());

            FileOutputStream fos = new FileOutputStream(fileToSave);

            int n;

            byte[] buffer = new byte[8192];

            System.out.println("Connected");    

            while ((n = bis.read(buffer)) > 0) {

                System.out.println("received "+n+" bytes");
                fos.write(buffer, 0, n);

                fos.flush();

            }

            System.out.println("recieved");

        }

        catch(Exception e) {

            e.printStackTrace();

        }

    }

}

我想在客户端连接后提示客户端用户输入文件名以发送到服务器,服务器应发送该文件。

我试图在 System.out.println("connected");

之后将它放在客户端
System.out.print("Insert filename to download: ");

    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

    String input = null;

    try {

       input = reader.readLine();

    } catch (IOException ioe) {

       System.out.println("Eingabe konnte nicht verarbeitet werden!");
       System.exit(1);

    }

    System.out.println("Eingabe: " + input);

在服务器端,我把它放在 outputStream = new BufferedOutputStream(clientSocket.getOutputStream()); 之后,以覆盖服务器开头的硬编码文件名 class。

        inputStream = new BufferedInputStream(clientSocket.getInputStream());

        fileInputStream = new FileInputStream(inputStream);

        fileInputStream = new BufferedInputStream(fileInput);

建立连接后,客户端处于空闲状态(无法输入内容),服务器端在写入控制台后什么也不做 "new connection"。

请问我该如何解决?

客户端向服务器发送文件名。所以首先你必须从套接字的输入流中提取文件名。为此,您需要建立一个关于如何发送信息的协议。这在处理不同于 UDP 数据报的 TCP 流时至关重要。通常使用两个换行符来传达消息的结尾。但是因为文件名中有换行符是不正常的,所以我们将使用一个换行符来表示消息的结束。

然后我们可以使用 Scanner 从客户端的套接字中提取文件名。

String fileName;
Scanner scanner = new Scanner (clientSocket.getInputStream());
while(scanner.hasNextLine())
{
    fileName = scanner.nextLine();
    break;
}
fileInputStream = new FileInputStream(fileName);
fileInputStream = new BufferedInputStream(fileInput);

在此示例中,文件名必须是该文件在服务器文件系统中的绝对路径。在未来的版本中,您可能希望使用服务器上存储文件的目录,客户端可以为您提供该目录中文件的相对路径。这是它的样子。

String fileName;
Scanner scanner = new Scanner (clientSocket.getInputStream());
while(scanner.hasNextLine())
{
    fileName = scanner.nextLine();
    break;
}
fileInputStream = new FileInputStream(FILE_DIR + fileName);
fileInputStream = new BufferedInputStream(fileInput);

变量 FILE_DIR 看起来像这样:

static String FILE_DIR = "C:/java/";

客户端发送的文件就是 file.mp4

编辑 1:

这是带有建议的客户端代码。请注意,此测试质量代码,而非生产代码。

import java.net.*;
import java.io.*;

public class Client {

    static String FILE_DIR = "./";

    public static void main(String[] s) throws IOException {

        /**
         * Establish socket using main args.
         */
        String address = s[0];

        while (true) {

            /**
             * Get the file name from the user.
             */
            System.out.print("Insert filename to download: ");
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            String fileName = null;
            try {
                fileName = reader.readLine();
            } catch (IOException ioe) {
                System.out.println("Eingabe konnte nicht verarbeitet werden!");
                System.exit(1);
            }
            System.out.println("Eingabe: " + fileName);

            /**
             * Create the socket.
             */
            Socket socket = new Socket(address, 12345);

            /**
             * With file name in hand, proceed to send the filename to the
             * server.
             */
            //...put in try-with-resources to close the outputstream.
            try (BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream())) {
                System.out.println("Connected:  Sending file name to server.");
                //...send file name plus a newline.
                bos.write((fileName + '\n').getBytes());
                bos.flush();

            /**
             * Get the file contents and save to disk.
             */
            //...wrap input stream in DataInpuStream for portability.
            //...put in try-with-resource to close the input stream.
            try (BufferedInputStream bis = new BufferedInputStream(new DataInputStream(socket.getInputStream()))) {
                DataOutputStream fos = new DataOutputStream(new FileOutputStream(fileName));
                int n;
                byte[] buffer = new byte[8192];
                System.out.println("Connected:  Recieving file contents from server.");
                while ((n = bis.read(buffer)) > 0) {
                    System.out.println("received " + n + " bytes");
                    fos.write(buffer, 0, n);
                    fos.flush();
                }
                System.out.println("recieved");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
     }
    }
}

这是服务器代码。请注意服务器正在从名为 ./files/ 的本地目录中检索文件,请将其更改为您想要的任何目录。

导入java.net.; 导入 java.io.; 导入 java.util.Scanner;

public class 服务器 {

static String FILE_DIR = "./files/";

public static void main(String[] args) {

    BufferedInputStream inputStream;
    FileInputStream fileInput;

    try {

        ServerSocket socket = new ServerSocket(12345);

        while (true) {
            Socket clientSocket = socket.accept();

            /**
             * Get the file name from the client. File name is one per line.
             */
            //...put in trye-with-resources to close InputStream for us.
            try (InputStream inputFromClient = clientSocket.getInputStream()) {
                System.out.println("Connected:  Getting file name from client.");
                Scanner scanner = new Scanner(inputFromClient);
                String fileName;
                if (scanner.hasNextLine()) {
                    fileName = scanner.nextLine();
                    System.out.println("File name = " + fileName);
                } else {
                    //...no line found, continue.  consider logging an error or warning.
                    continue;
                }

                /**
                 * With fileName in hand, we can proceed to send the
                 * contents of the file to the client.
                 */
                fileInput = new FileInputStream(fileName);
                //...use DataInputStream for more portable code
                DataInputStream dataInput = new DataInputStream(fileInput);
                inputStream = new BufferedInputStream(dataInput);
                int packetToSend = -1;
                byte[] buffer = new byte[8192];

                //...consider closing the OutputStream to let the client know.
                //...use try-with-resource to close the outputStream for us.
                //...wrap your outputStream in DataOutputStream
                try (BufferedOutputStream outputStream = new BufferedOutputStream(new DataOutputStream(clientSocket.getOutputStream()))) {
                    while ((packetToSend = inputStream.read(buffer)) > -1) {
                        outputStream.write(buffer, 0, packetToSend);
                        System.out.println("sending " + packetToSend + " bytes");
                        outputStream.flush();
                    }
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
}