首页 > 解决方案 > 能够成功写入数据但无法从服务器读取数据

问题描述

我有两个类服务器和客户端。我在 intelliji 上同时运行服务器和客户端。我能够将数据写入服务器上的 Json 文件,但是在读取数据时,我无法读取它。当我尝试读取数据时,我的应用程序没有响应。我是套接字编程的新手,请帮助我。

这是客户端的代码

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

public class Client {
    public String readDataFromServer(Socket socket) throws IOException {

        InputStreamReader inputStreamReader = new 
        InputStreamReader(socket.getInputStream());
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

        return bufferedReader.readLine();
    }

    public  void writeDataToServer(String obj) throws IOException {
        Socket socket = new Socket("localhost", 1299);
        OutputStreamWriter outputStreamWriter = new 
        OutputStreamWriter(socket.getOutputStream());
        PrintWriter printWriter = new PrintWriter(outputStreamWriter);
        printWriter.write(obj);
        printWriter.flush();
        printWriter.close();
    }
}

这是服务器端的代码

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    static void writeJson (String str) throws IOException {
        FileWriter pw = null;
        try {
            pw = new FileWriter("MYJSON.json", true);
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        }
        pw.write(str + '\n');
        pw.flush();
        try {

        } catch (Exception E) {
            E.printStackTrace();
        }
        pw.close();
    }

    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(1299);
        Socket socket = serverSocket.accept();

        InputStreamReader inputStreamReader = new     InputStreamReader(socket.getInputStream());
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        String str = bufferedReader.readLine();
        writeJson(str);

        FileReader fileReader = new FileReader("MYJSON.json");
        BufferedReader buff = new BufferedReader(fileReader);
        OutputStreamWriter outputStreamWriter = new 
        OutputStreamWriter(socket.getOutputStream());
        PrintWriter printWriter = new PrintWriter(outputStreamWriter);

        printWriter.write(buff.readLine());
        printWriter.flush();  
    }
}

我有另一个名为显示控制器的类,它调用方法,该方法通过传递套接字对象来调用方法。这是这个类的一段代码。

Client client = new Client();
button1.setOnAction(e-> {
            try {
                String str;

              while ((str = client.readDataFromServer(socket)) != null) {

                Object obj = null;
                try {
                  obj = jsonParser.parse(str);

我在这里做错了什么?我如何解决它?谢谢

标签: javajsonsockets

解决方案


您的代码中有几个问题。

  1. 主要的是在 Server 类的 main 方法中。您的服务器只接受一个连接。该连接写入和读取 json 文件,然后您的 main 方法结束。如果你的主程序结束,那么服务器就消失了。这意味着第一个连接的客户端将工作并写入文件,但任何后续连接都不会连接,因为不再有服务器接受连接。典型的服务器通过使用 while 循环true作为条件无限期地运行。

没有线程的服务器的示例结构:

    public class Server {

      // this class represents an instance of a client connection to this server
      // It's an object that keeps track of the socket created by referencing
      // the connection.
      private class ClientInstanceOnTheServer {

        private Socket connectionToClient;

        public ClientInstanceOnTheServer(Socket connectionToClient) {
          this.connectionToClient = connectionToClient;
        }

        private void logicToServeAClient() {
          // here goes the logic that serves a client
        }

        public void run () {

          try {
            logicToServeAClient();
          } finally {
            try {
              socket.close();
            } catch (IOException e) {// handle exceptions!}
          }

        }

      }

      public static void main(String [] args) {
        try {
          ServerSocket serverSocket = new ServerSocket(1299);
          while (true) { // run indefinitely
             Socket socket = serverSocket.accept(); // accept connections from clients
             // keep track of the socket object as it represents a connection to a client
             // the server is responsible for keeping track of its connections to clients
             // Example:
             ClientInstanceOnTheServer client = new ClientInstanceOnTheServer(socket);
             client.run();
          }
        } finally {
          serverSocket.close();
        }
      }
    }

带有线程的服务器的示例结构: 注意:下面的代码不是代表带有线程的完整解决方案,而是解释服务器如何工作的示例。

    public class Server {

      // this class represents an instance of a client connection to this server
      // It's an object that keeps track of the socket created by
      // the connection and it runs in a separate thread to not block
      // the main method thread on this server.
      private class ClientInstanceOnTheServer extends Thread {

        private Socket connectionToClient;

        public ClientInstanceOnTheServer(Socket connectionToClient) {
          this.connectionToClient = connectionToClient;
        }

        private void logicToServeAClient() {
          // here goes the logic that serves a client
        }

        public void run () {

          try {
            logicToServeAClient();
          } finally {
            try {
              socket.close();
            } catch (IOException e) {// handle exceptions!}
          }

        }

      }

      public static void main(String [] args) {
        try {
          ServerSocket serverSocket = new ServerSocket(1299);
          while (true) { // run indefinitely
             Socket socket = serverSocket.accept(); // accept connections from clients
             // keep track of the socket object as it represents a connection to a client
             // the server is responsible for keeping track of its connections to clients
             // and it should use a separate thread for each client to not block the main method thread.
             // Example:
             ClientInstanceOnTheServer client = new ClientInstanceOnTheServer(socket);
             client.start(); // this will execute the run method in ClientInstanceOnTheServer class.
          }
        } finally {
          serverSocket.close();
        }
      }
    }
  1. 无论客户端想要什么,您的服务器总是同时执行写入和读取 json 文件。服务器应该以某种方式允许客户端传达它想要做的事情,然后它只执行客户端要求的内容。如果我们使用上面的骨架代码,这个逻辑将进入类的方法logicToServeAClientClientInstanceOnTheServer。服务器和客户端使用socket对象的输入和输出流相互通信。服务器和客户端需要事先就客户端需要和服务器愿意服务的命令/操作达成一致。在您的情况下,它将是READand WRITE。然后,您在客户端和服务器之间创建一个关于如何将这些命令发送到服务器以及服务器将如何对每个命令响应客户端的合同(协议)。

协议示例:

// client sends READ to server
// client waits for respond from server
// server read json file and send it to the client

// client sends WRITE to server
// server then waits for the client to send the string to write. 
// Once it receives the string, it writes it to the json file.

所有这些都可以使用套接字的输入和输出流来实现

区分 theClientClientInstanceOnTheServerclasses 之间的区别很重要。Client 是您的Client类,它连接到服务器并ClientInstanceOnTheServer保持连接,还运行服务器代码,为Client类请求的命令提供服务。在上面的协议中,每当提到客户端时,都是指Client类。每当提到服务器时,都是指ClientInstanceOnTheServer类。

您可以在 google 上找到更多示例,例如:http ://cs.lmu.edu/~ray/notes/javanetexamples/ 。但是,这应该会让您走上解决问题的道路。

干杯


推荐阅读