【问题标题】:Socket Client-Server gets stuck after sending to server sideSocket Client-Server 发送到服务器端后卡住
【发布时间】:2016-03-29 15:12:54
【问题描述】:

我需要为我的项目制作一个带有 Sockets 的文件传输应用程序。到目前为止,我已经编写了一个简单的客户端-服务器通信,但是每当我尝试从客户端输出接收字符数据到服务器输入时,我的代码都会锁定。代码如下:

服务器

public class ClientServer extends Thread {

Socket connection;
File file;

public ClientServer (Socket connection){
    this.connection = connection;
    this.start();
}

public void run(){
    try {
        System.out.println("Starting Client Thread...");
        BufferedReader input = new BufferedReader(new InputStreamReader(connection.getInputStream()));
        DataOutputStream output = new DataOutputStream(connection.getOutputStream());
        System.out.println("IO created...");
        System.out.println("input = " + input.readLine());

        String s = input.readLine();

        System.out.println(s);
        file = new File(s);

        if(file.isFile()){
            System.out.println("File " + s + " exists");

            FileInputStream fileOutput = new FileInputStream(file);
            byte[] buffer = new byte[1024*1024];
            int length = 0;
                while((length = fileOutput.read(buffer)) != -1){
                    output.write(buffer, 0, buffer.length);
                }
            System.out.println("File " + s + " sent.");
            fileOutput.close();
            output.close();
            input.close();
        } else {
            System.out.println(s + " is not a file");
        }

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    finally{
        try {
            connection.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }               
}


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

    int serverPort = 9000;

    ServerSocket server = new ServerSocket(serverPort);

        Socket connectionSocket = server.accept();

        ClientServer con = new ClientServer(connectionSocket);
}
}

客户

public static void main(String[] args) throws IOException {
    // TODO Auto-generated method stub

    String ip = "localhost";
    int port = 9000;
    Socket clientSocket = new Socket(ip, port);


    BufferedWriter out = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));

    DataInputStream in = new DataInputStream(clientSocket.getInputStream());

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

    System.out.println("Enter valid file name and press 'ENTER': ");

    String message = userInput.readLine();
    System.out.println("Sending message...");
    out.write(message);
    System.out.println("File name sent: " + message);

    int length = in.readInt();
    byte[] buffer = new byte[length];
    for(int i=0; i< length; i++){

        buffer[i] = in.readByte();
        System.out.println("Reading byte... " + buffer[i]);
    }
    File file = new File("C:/Users/Dominik/Desktop/lol/new.php");
    FileOutputStream fos = new FileOutputStream(file);
    fos.write(buffer);
    fos.close();

    clientSocket.close();
    System.out.println("Closing");
}
}

编辑

这是我的输出,因为没有一个答案能解决我的问题(可能是我做错了什么):

客户

Enter valid file name and press 'ENTER': C:\\Users\\Dominik\\Desktop\\Login.php //my input Sending message... File name sent: C:\\Users\\Dominik\\Desktop\\Login.php

服务器

Starting Client Thread... IO created... //Server should sysout the message sent, but it doesn't do so, its just stuck here

【问题讨论】:

  • 你有执行的输出吗?你有很多日志可以帮助指出问题
  • 你能告诉我你想做什么。我想你想传输文件。对吗?
  • 你的FileInputStream到底为什么叫fileOutput?不要写这样的代码。请。
  • 我想通过客户端输入的路径从服务器传输文件。

标签: java sockets io


【解决方案1】:

您尝试在客户端readInt,但在服务器端您只发送文件内容。我看你在发送文件之前忘记发送文件大小了。

【讨论】:

    【解决方案2】:

    你正在读一行:

    String s = input.readLine();
    

    但你没有写一行:

    out.write(message);
    

    为此添加行终止符。

    然后:

    int length = in.readInt();
    

    在这里,您正在读取一个从未发送过的整数。发送它。

    【讨论】:

    • 嗯,所以你建议我应该做类似 'out.write(message + '\n') 的事情?我就是这样做的,但没有奏效。 fileOutput 是我这边的一个错误,没有注意它。通信仍然锁定在服务器端的“IO created...”调试消息上。有什么想法吗?
    • 我提出了 两个 建议,没有一个。我不需要告诉我我的建议。
    • 我也实现了另一个,但是代码没有达到int length = in.readInt(),它在第一次写入服务器的输入后锁定。我感谢这位帮助者,这只是令人沮丧,因为我连续 2 天坐在这里没有任何进展。如果您有任何其他想法,我将非常高兴听到它们。
    【解决方案3】:

    我认为你的通信协议有错误:

    在您的服务器中,连接后,您期望来自客户端的两个后续字符串

        System.out.println("input = " + input.readLine());
    
        String s = input.readLine();
    

    但客户端只发送一个(我认为您也应该按照 EJP 的建议添加一个行终止符)

    然后客户端需要一个整数,但服务器没有发送它:

        int length = in.readInt();
    

    希望对你有帮助,祝你好运

    编辑(在 12 月 23 日编辑之后)

    添加你的客户端

    out.flush();
    

    在你之后

    out.write(message + "\n");
    

    然后修复协议。

    我采纳了你得到的所有建议,并且成功了

    服务器:

        public class ClientServer extends Thread {
    
            Socket  connection;
            File    file;
    
            public ClientServer(Socket connection) {
                this.connection = connection;
                start();
            }
    
            @Override
            public void run() {
                try {
                    System.out.println("Starting Client Thread...");
                    BufferedReader input = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                    DataOutputStream output = new DataOutputStream(connection.getOutputStream());
                    System.out.println("IO created...");
                    // System.out.println("input = " + input.readLine());
    
                    String s = input.readLine();
    
                    System.out.println(s);
                    file = new File(s);
    
                    if (file.isFile()) {
                        System.out.println("File " + s + " exists");
    
                        FileInputStream fileInput = new FileInputStream(file);
                        output.writeInt((int) file.length());
                        byte[] buffer = new byte[1024 * 1024];
                        int length = 0;
                        while ((length = fileInput.read(buffer)) != -1) {
                            output.write(buffer, 0, length);
                        }
                        System.out.println("File " + s + " sent.");
                        fileInput.close();
                        output.close();
                        input.close();
                    }
                    else {
                        System.out.println(s + " is not a file");
                    }
    
                }
                catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
    
                finally {
                    try {
                        connection.close();
                    }
                    catch (IOException e) {
                        e.printStackTrace();
                    }
    
                }
            }
    
            public static void main(String[] args) throws IOException {
    
                int serverPort = 9000;
    
                ServerSocket server = new ServerSocket(serverPort);
    
                Socket connectionSocket = server.accept();
    
                ClientServer con = new ClientServer(connectionSocket);
            }
        }
    

    客户:

        public class Client {
    
            public static void main(String[] args) throws IOException {
                // TODO Auto-generated method stub
    
                String ip = "localhost";
                int port = 9000;
                Socket clientSocket = new Socket(ip, port);
    
                BufferedWriter out = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
    
                DataInputStream in = new DataInputStream(clientSocket.getInputStream());
    
                BufferedReader userInput = new BufferedReader(new InputStreamReader(System.in));
    
                System.out.println("Enter valid file name and press 'ENTER': ");
    
                String message = userInput.readLine();
                System.out.println("Sending message...");
                out.write(message + "\n");
                out.flush();
                System.out.println("File name sent: " + message);
    
                int length = in.readInt();
                byte[] buffer = new byte[length];
                for (int i = 0; i < length; i++) {
    
                    buffer[i] = in.readByte();
                    System.out.println("Reading byte... " + buffer[i]);
                }
                File file = new File("C:/test/fromServer.txt");
                FileOutputStream fos = new FileOutputStream(file);
                fos.write(buffer);
                fos.close();
    
                clientSocket.close();
                System.out.println("Closing");
            }
        }
    

    【讨论】:

      【解决方案4】:

      只是对所有有用答案的一个小补充:
      在服务器端写入 length 文件字节 - output.write(buffer, 0, length);
      不要使用 buffer.length,这通常会导致 java.net.SocketException: Broken pipe 因为客户端会在收到length 字节后立即关闭套接字,但服务器正在尝试写入整个 1024*1024 缓冲区。

      同样在客户端你可以摆脱 for 循环并像这样接收文件内容

      byte[] buffer = new byte[length];
      int bytesRead = in.read(buffer);
      if (bytesRead != length) {
          ; // handle incomplete file transfer
      }
      

      【讨论】:

      • 不,你不能。 in.read(buffer) 不保证会填满缓冲区。请参阅 Javadoc。
      • @EJP 已经有一段时间了。你是对的,值得将接收到的从read(buffer) 返回的消息的长度与文件的预期长度进行比较。为了简单起见,我想我没有提到它。
      • 所以修正你的答案!
      • 完成。感谢您引起我的注意!
      猜你喜欢
      • 2018-07-23
      • 1970-01-01
      • 2019-01-02
      • 2017-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多