当前位置: 首页 > 知识库问答 >
问题:

输出流处的服务器-客户端通信失败

慕容修伟
2023-03-14

我的程序基本上是:

>

  • 客户端向服务器发送字符串,

    基于这个字符串,服务器正在创建一个ArrayList,

    ArrayList 被发送回客户端。

    这里失败的是:

    客户端发送字符串后,服务器会收到它,并且不执行任何其他操作。在这段时间里,客户端继续工作并得到一个空指针

    客户端:

        public static ArrayList<String> sendStringToServer(String report) {
    
        Socket socket;
    
        ArrayList<String> fieldsList = new ArrayList<String>();
    
        try {
    
            socket = new Socket("localhost", 2345);
    
            OutputStream os = socket.getOutputStream();
            PrintStream ps = new PrintStream(os, true);
    
            ps.println(report);
            ps.flush();
    
            //Here the debugger should stop and wait for server to create a List
    
            //at this point there is no answer, code breaks
            ObjectInputStream objectInput = new ObjectInputStream(socket.getInputStream());
    
            Object object = objectInput.readObject();
            fieldsList = (ArrayList<String>) object;
    
            socket.close();
    
            return fieldsList;
    
        } catch (IOException e1) {
    
            e1.printStackTrace();
        } catch (Exception e) {
    
            e.printStackTrace();
        }
        return null;
    }
    

    }

    服务器端:

    public class Server {
    
    private ServerSocket serverSocket;
    private Socket clientSocket;
    private String telegram;
    private StringBuilder telegramSB;
    
    public static void main(String[] args) throws IOException, JRException {
    
        new Server();
    }
    public Server() {
    
        try {
            serverSocket = new ServerSocket(2345);
    
            while (true) {
    
                clientSocket = serverSocket.accept();
                InputStream is = clientSocket.getInputStream();
                InputStreamReader isr = new InputStreamReader(is);
                BufferedReader br = new BufferedReader(isr);
    
                try {
    
                    //debugger goes to here and then stops
                    telegram = br.readLine();
    
                    int counter = 0;
    
                    boolean startSeq = false;
    
                    for (char ch : telegram.toCharArray()) {
    
                        if (counter == 0 && ch == '/') {
    
                            startSeq = true;
                        }
    
                        if (startSeq == true) {
    
                            telegramSB = new StringBuilder();
                            telegramSB.append(ch);
                        }
    
                        if (ch == '\n') {
    
                            if (telegram.length() < 255) {
    
                                sendListWithFields();
    
                            } else {
    
                                new Launcher(telegram).run();
                            }
                        }
                        counter++;
                    }
                } catch (JRException e) {
    
                    e.printStackTrace();
    
                } catch (IOException e) {
    
                    e.printStackTrace();
    
                }
            }
        } catch (IOException e) {
    
            System.out.println(e);
        }
    }
    
  • 共有1个答案

    融烨磊
    2023-03-14

    我的猜测是,BufferedReader正在等待填充它的缓冲区,而你还没有发送足够的数据让它这样做并返回,所以它一直在等待更多的数据通过(因为你的客户机停止写并开始读)。您可以通过将更多的数据转储到客户机的OutputStream中并刷新它来暂时测试这个理论。

    如果是上述情况,那么您可能不想使用BufferedReader,但您还有其他问题,这也意味着您可能希望避免使用PrintStream和BufferedReader进行通信和序列化。例如,两台不同机器和JVM上的默认字符编码可能不同。当您创建PrintStream和InputStreamReader时,您没有指定字符编码,因此它们可能会不匹配,您编写的字符串(包括换行符)可能会被远程端完全不同地理解,这也可能是其阻塞的原因(客户端以一种方式编码换行符,但服务器希望它以完全不同的方式编码),尽管我认为可能性不大。

    如果您不必使用PrintStream,那么我建议您改用DataOutpuStream/DataInpuStream:

    //Client
    BufferedOutputStream bufout = new BufferedOutputStream(socket.getOutputStream());
    DataOutputStream dout = new DataOutputStream(bufout);
    dout.writeUTF(report);
    dout.flush();
    
    //Server
    BufferedInputStream bufin = new BufferedInputStream(socket.getInputStream());
    DataInputStream din = new DataInputStream(bufin);
    String report = din.readUTF();
    

    您仍然可以从BufferedIn/OutputStreams获得缓冲,因此它将是高性能的,但是DataIn/OutputStreams将为您管理可变长度对象的终止——它们将发送一个长度作为字符串的前缀,以告诉另一端要读取的确切字节数,因此您不需要使用特殊字符来终止您编写的字符串,这也意味着字符串的内容是什么并不重要。在上面的例子中,如果你的字符串中有一个换行符,服务器会一直读到第一个换行符,而不是读到你发送的字符串的末尾,这会使它们在下一次发送/接收时不同步。

    使用写/读UTF还指定了编码(UTF-8),因此也没有不匹配。

     类似资料:
    • 现在我的ServerSocket是这样的 一切正常,客户端连接,发送一些数据,服务器读取它,但我的问题是如何从我的服务器发送消息到所有的客户端?我目前保存客户端上的ArrayList,所以我可以只是循环,ArrayList打开一个作家和刷新它,但我想发送的数据,我得到我的ClientConnection类 我应该如何处理这个代码?在服务器类上完成的所有操作?或

    • 我对spring boot和SSL还很陌生。我已经开发了一个SSL rest web服务器,它具有服务器密钥存储库、私钥和服务器CA,并且能够正确地处理相互X.509证书身份验证。我已经测试过,它可以与Postman和Python客户机一起工作HTTPS请求,并且所有工作都正常,服务器和客户机都可以成功地交换和验证对方的证书。 但我的情况有点不同, 我已经创建并连接了一个Postgresql数据库

    • 我对套接字有点陌生,我正在尝试编写一个程序,在这个程序中,我基本上可以从客户端程序向服务器程序发送一些简单的请求。现在我只想在客户端有1或2个选项供用户选择。例如,如果用户在客户端选择“选项1”,那么服务器会返回一条消息“您选择选项1”,以此类推,但我不知道如何读取服务器上从客户端发送的输入。 客户代码: 服务器代码: 我需要在Clinet中使用两个不同的BufferedReader吗?一个用于用

    • 我试图了解服务器-客户端网络如何为实时多人游戏工作。 假设我正在构建一个实时多人游戏,比如FPS。 如果玩家A向玩家B开枪,后端< code >服务器需要告诉玩家B他们被击中了。 我知道如何让玩家 A 告诉后端服务器他开了一枪,只是向服务器发送请求,但是如何让后端告诉玩家 他们被枪杀了? 玩家B是否必须每0.1秒检查一次后端以查看是否发生了什么事情,或者是否有更有效的方法?

    • 问题内容: 我正在构建一个小型聊天应用程序,其中客户端A希望通过服务器B将某些东西发送到客户端C。首先,这是解决问题的正确方法吗?我能够向服务器发送数据或从服务器接收数据,但仅限于客户端。例如,如果客户端A向服务器B发送数据而客户端C向服务器B发送数据,则我可以将数据发送回服务器A和C就像回显服务器一样。但是我想要的是将来自客户端A的数据通过服务器B转发到客户端C。 以下是服务器代码: 客户端代码

    • 问题内容: 我目前处于论文项目的研究阶段。 我的项目是用于移动设备的票务预订系统,我选择了以Android为目标。 我预计需要具有中央服务器的客户端/服务器架构,因此目前正在研究Android如何与此类服务器进行通信。服务器将授予客户端访问票务信息的权限,客户端会将有关票务预订的信息发送到服务器。我正在寻找服务器的Java EE,因为Java是我最有经验的语言。 我知道Android附带了和以及一