具有消息(文本)和文件传输的 Java Socket 多用户聊天应用程序

Posted

技术标签:

【中文标题】具有消息(文本)和文件传输的 Java Socket 多用户聊天应用程序【英文标题】:Java Socket Multi user chat app with both message (text) and file transfer 【发布时间】:2021-12-22 02:45:22 【问题描述】:

我是 Java 新手。我正在通过制作一个聊天应用程序来学习套接字和线程编程,其中从客户端发送的消息将被服务器接收,服务器会将其发送给另一个客户端。

服务器是这样工作的。字符串的第一个单词是命令,其余是参数。

发消息的命令 示例:味精 jony 嗨!

这将发送嗨!给客户名字 jony。 //

login tom tom123 // 将使用用户名“tom”和密码“tom123”登录 tom

现在我想添加文件传输。所以一个客户端可以将文件发送到另一个客户端。据我所知,我需要使用 DataInputStream 。在这种情况下,如何让服务器区分以下程序中的文件和文本?或者我可以像“file jony c://abc.txt”一样将 abc.txt 文件发送给 jony?

已编辑:看起来像 handleFile 被调用,但它什么都没有。 (如果像handfleFile()一样在开始时调用hangle文件,它就可以工作;

我做错了什么:(

这是我的服务器代码的一部分。

    private void handleClientSocket() throws IOException, InterruptedException, SQLException 
//        InputStream inputStream = clientSocket.getInputStream();
//        this.outputStream = clientSocket.getOutputStream();
//        DataInputStream inputStream = new DataInputStream(clientSocket.getInputStream());
        this.outputStream = new DataOutputStream(clientSocket.getOutputStream());
        this.inputStream = new DataInputStream(clientSocket.getInputStream());

        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        String line;
        Connect(); //Connects to databse
//        handleFile();
        while ( (line = reader.readLine()) != null) 
            String[] tokens = StringUtils.split(line);
            if (tokens != null && tokens.length > 0) 
                String cmd = tokens[0];
                if ("quit".equalsIgnoreCase(cmd) || "logoff".equalsIgnoreCase(cmd)) 
                    handleLogOff();
                    break;
                 else if ("login".equalsIgnoreCase(cmd)) 
                    handleLogin(outputStream, tokens);
                 else if ("msg".equalsIgnoreCase(cmd)) 
                    String[] tokenMsg = StringUtils.split(line, null, 3);
                    handleMessage(tokenMsg);
                 else if ("join".equalsIgnoreCase(cmd)) 
                    handleJoin(tokens);
                 else if ("leave".equalsIgnoreCase(cmd)) 
                    handleLeave(tokens);
                 else if ("signup".equalsIgnoreCase(cmd)) 
                    handleSignUp(tokens);
                 else if ("create".equalsIgnoreCase(cmd)) 
                    handleCreateGroup(tokens);
                 else if ("sendFile".equalsIgnoreCase(cmd)) 
//                    inputStream.close();
                    handleFile();
                

                else 
                    String msg = "Unknown command: " + cmd + "\n";
                    outputStream.write(msg.getBytes());
                
            
        
    

    private void handleFile ()
        System.out.println("File handler called");
        try 
            System.out.println("File handler called");
//            DataInputStream input = new DataInputStream(clientSocket.getInputStream());
            DataInputStream inputStream = new DataInputStream(clientSocket.getInputStream());
            int fileNameLength = inputStream.readInt();
            System.out.println(fileNameLength);
            if (fileNameLength > 0) 
                byte[] fileNameBytes = new byte[fileNameLength];
                inputStream.readFully(fileNameBytes, 0, fileNameBytes.length);
                String fileName = new String(fileNameBytes);
                System.out.println(fileName);
                int fileContentLength = inputStream.readInt();
                System.out.println(fileContentLength);
                if (fileContentLength > 0) 
                    byte[] fileContentBytes = new byte[fileContentLength];
                    inputStream.readFully(fileContentBytes, 0, fileContentBytes.length);
                    System.out.println(fileContentBytes);

//                    File fileToDownload = new File(fileName);
                    FileOutputStream fileOutputStream = new FileOutputStream("D:\\bbb.txt");
                    fileOutputStream.write(fileContentBytes);
                    fileOutputStream.close();
                
            

这是客户端代码:

public class Main 

    public static void main(String[] args) 
        Scanner scanner = new Scanner(System.in);
//        final File[] fileToSend = new File[1];
//        fileToSend[0] = "C:\\Users\\alvyi\\Downloads";
        File file = new File("D:\\aaa.txt");

        try 
            Socket socket = new Socket("localhost", 6000);
            DataInputStream inputStream = new DataInputStream(socket.getInputStream());

            DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
        while(true)
            System.out.println("In the Loop");

            dataOutputStream.write("login alvy alvy\n".getBytes(StandardCharsets.UTF_8));
            dataOutputStream.write("sendFile\n".getBytes(StandardCharsets.UTF_8));

            FileInputStream fileInputStream = new FileInputStream(file.getAbsolutePath());
            String fileName = file.getName();
            // Convert the name of the file into an array of bytes to be sent to the server.
            byte[] fileNameBytes = fileName.getBytes();
            // Create a byte array the size of the file so don't send too little or too much data to the server.
            byte[] fileBytes = new byte[(int)file.length()];
            // Put the contents of the file into the array of bytes to be sent so these bytes can be sent to the server.
            fileInputStream.read(fileBytes);
            // Send the length of the name of the file so server knows when to stop reading.
            dataOutputStream.writeInt(50);
            dataOutputStream.writeInt(fileNameBytes.length);
            // Send the file name.
            dataOutputStream.write(fileNameBytes);
            // Send the length of the byte array so the server knows when to stop reading.
            dataOutputStream.writeInt(fileBytes.length);
            // Send the actual file.
            dataOutputStream.write(fileBytes);



            String echoString = scanner.nextLine();
        
    //        System.out.println(inputStream.readLine());

     //       outputStream.write("sendFile".getBytes());



         catch (IOException e) 
            e.printStackTrace();
        



    


【问题讨论】:

【参考方案1】:

在这种情况下,如何让服务器区分以下程序中的文件和文本?或者我可以像“file jony c://abc.txt”一样将 abc.txt 文件发送给 jony?

可用性的角度来看,将send file 命令作为聊天 API 中的单独命令是有意义的。因此,添加一个不同的命令来使用像file 这样的描述性名称的想法是有意义的。

如果要谈API的实现,那么这就是标准问题的标准解决方案。

这里是code,它解释了如何通过套接字发送文件。

【讨论】:

是的,我这样做了,但看起来它什么也没做。但是,如果我在开始时调用该方法(当前已评论),它会起作用!!!我现在头疼:/ 那为什么不一开始就调用呢? 那会破坏整个目的。我只想在客户端发送命令 sendFile 时发送文件。如果我一开始就使用它,那么我每次都需要发送一个文件,然后才能开始做其他事情。我已经更新了代码。如果可能的话,请看一下:( 谢谢,终于明白了 BufferReader 导致了所有问题。使用 inputStream.readLine() 解决了这个问题。 (家庭它不会在未来引起问题哈哈) 如果我的回答对您有所帮助,请随时将答案标记为已接受并点赞

以上是关于具有消息(文本)和文件传输的 Java Socket 多用户聊天应用程序的主要内容,如果未能解决你的问题,请参考以下文章

HTTP协议简介

HTTP协议简介

Ms-Access 尝试使用“传输文本”创建具有唯一文件名的 csv 文件

文件传输, socketserver模块

python运维开发----socket

使用java每秒流式传输大量数据