如何在java上从套接字读取多种类型的数据

如何在java上从套接字读取多种类型的数据,java,sockets,serversocket,Java,Sockets,Serversocket,我写了一些文件传输应用程序。在客户端和服务器之间,我发送3种类型的数据: 1) 一些“命令词”,如READY_FOR_UPLOAD 2) 一些可序列化的数据 3) 字节数组中的大文件 我在服务器套接字上获得客户端连接,并为每个客户端创建新线程 try (BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); PrintWriter out = new

我写了一些文件传输应用程序。在客户端和服务器之间,我发送3种类型的数据:

1) 一些“命令词”,如READY_FOR_UPLOAD

2) 一些可序列化的数据

3) 字节数组中的大文件

我在服务器套接字上获得客户端连接,并为每个客户端创建新线程

    try (BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
    PrintWriter out = new PrintWriter(clientSocket.getOutputStream(),true);
    InputStream inputStream = clientSocket.getInputStream();
    ObjectInputStream objectInputStream = new ObjectInputStream(inputStream)) {}
我使用try-with-resources创建这些流,没有问题

我使用:

1) “in”用于从客户端读取消息:

    String line;
    while ((line = in.readLine()) != null) {
      System.out.println(line);
    }
2) “out”用于发送消息

3) 接收文件的“inputStream”:

    try (FileOutputStream fileOutputStream = new  
              FileOutputStream("D:\\testDownload.zip");
         BufferedOutputStream bufferedOutputStream = new 
               BufferedOutputStream(fileOutputStream)
            ) {
                byte[] buffer = new byte[1024 * 100];
                int read;
                while ((read = inputStream.read(buffer)) != -1) {
                   bufferedOutputStream.write(buffer, 0, read);
                }

            }
4) 可序列化数据的“objectInputStream”:

    Object object;
    if ((object = objectInputStream.readObject()) != null) {
        if (object instanceof File) {
              File file = (File) object;
              System.out.println(file.getAbsolutePath());
              System.out.println(file.length());
          }
     }
虽然我单独使用它们,但没有问题。但我首先需要阅读“命令词”,即在我的tread的方法运行的开始部分

    public void run() {
    try (BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
    PrintWriter out = new PrintWriter(clientSocket.getOutputStream(),true);
    InputStream inputStream = clientSocket.getInputStream();
    ObjectInputStream objectInputStream = new ObjectInputStream(inputStream)) {
      String line;
     if ((line = in.readLine()) != null) {
      System.out.println(line);

     there i should try to read other types of data
    }
    }

如果这不是“命令字”,我可以尝试读取可序列化数据或文件数据。但这是个问题!我可能会尝试读取一行,但它可能是文件数据的可序列化数据的一部分,并且因为InputsReaded是“逐个”字节方法,所以我无法尝试像可序列化或文件数据那样读取它,因为输入不再完整,我在“readLine()”中读取了一些数据。在我尝试阅读之前,我应该知道我收到的是什么类型的数据。如何做到这一点?

您需要创建一个协议-规定客户端和服务器之间如何交换信息。
写入数据时,指定要发送的数据类型及其大小。不要在套接字上使用ObjectInputStream和ObjectOutputStream—将数据转换为字节数组,以便在编写时知道大小,然后将其转换回。以字节形式发送数据。

多次包装相同的InputStream或OutputStream,同时使用包装的实例可能会导致难以诊断的错误,因为这些流可能会进行内部缓冲。实际上,您要做的是将不同的输出流多路复用到单个输出流上,以使其正常工作。您需要定义一个协议,使接收器能够毫不含糊地恢复这些流。