Search code examples
javasocketsserversocket

How to read multiple types of data from socket on java


I write some file transfer application. Between client and server i send 3 type of data:

1) Some "command words" like READY_FOR_UPLOAD.

2) Some serializable data

3) Big files in byte array.

I get client connections on server socket and create new Thread for every client.

    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)) {}

I create these streams using try with resources and there is no problem.

I use:

1) "in" for read messages from client:

    String line;
    while ((line = in.readLine()) != null) {
      System.out.println(line);
    }

2)"out" for send messages.

3)"inputStream" for receive files:

    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" for serializable data:

    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());
          }
     }

While i use them separately - there is no problem. But i need read "command word" first of all i.e. in start of the method run of my 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
    }
    }

And if this is no "command word" i can try read serializable data or file data. But this is a problem! I may try to read a line but it can be part of serializable data of file data and because inputsream readed "one-by-one" byte method, i can't try read it like serializable or file data, because input not whole anymore, i read some data in "readLine()". I should know what type of data i receive before i try to read it. How can it be done?


Solution

  • You need to create a protocol - rules how client and server exchange information between them. When you write data you specify what data type you are sending and its size. And don't use ObjectInputStream and ObjectOutputStream on Socket - convert the data into array of bytes, so that you know what the size is when you writing and then convert them back. Send the data as bytes.