Vinit ...
Vinit ...

Reputation: 1459

Java: receive different type of file from InputStream in socket programming

In my project client send some text, some images to the server. Server need to handle all these things i.e if text is there then it need to display on TestArea which is on frame and if image file is there then server need to store that image file on the computer. I created one application which handle either string(text) or image file but I don't know how to store all these things when these are send by the client at the same time.

I know when I add this code: InputStream in = socket.getInputStream();

then all the data send by the client is in this InputStream So how I identify up to this much range data is image file so need to store in Byte Array, up to this much is test or string so need to display in TextAreea. If client send two or more images at a time to the server then how server understand up to this much data this is first image, up to this much data this is second image file.

I tried this code to send Images:

Client Code:

public void sendPhotoToServer(String str){ // str is image location
try {
    InputStream input = new FileInputStream(str);
    byte[] buffer=new byte[1024];
    int readData;
    while((readData=input.read(buffer))!=-1){
    dos.write(buffer,0,readData); // dos is DataOutputStream
    }
} catch (FileNotFoundException e) {

} catch (IOException e) {

}       
}

and this method is in the loop so client send all the images in his folder.

Now Server Code, this is in thread and while loop is there which listen client data every time:

public void run() {
while (true) {
        try {
            byte[] buffer = new byte[8192];
            fis = new FileOutputStream("C:\\"+(s1++)+".jpg"); // fis is FileOutputStream
            while ((count = in.read(buffer)) > 0){ //count is a integer and 'in' is InputStream
            fis.write(buffer, 0, count); 
            fis.flush();    
            }
            } catch (Exception e) {}
}
}

but by this code first image is received by the server after that it not show other images.

and here how server understand if simple string is send by the client. In server side application it open one port to listen all the data send by the client by

FileOutputStream fis = socket.getInputStream();

now how it distinguish all these files and simple string.

Upvotes: 1

Views: 3149

Answers (3)

Andrey Balaguta
Andrey Balaguta

Reputation: 1308

Why don't you just use ObjectInputStream and ObjectOutputStream, if you know the datatypes in advance.

Here's sending:

import java.io.*;

public class Client {

  public static void main(String[] args) throws IOException {
    // write string
    ObjectOutputStream out = new ObjectOutputStream(
      new BufferedOutputStream(
        new FileOutputStream("test-string.data")));
    try {
      out.writeObject("Hello");
    } finally {
      out.close();
    }
    // write byte arrays
    out = new ObjectOutputStream(
      new BufferedOutputStream(
        new FileOutputStream("test-byteArrays.data")));
    try {
      out.writeObject(new byte[] { 'H', 'e', 'l', 'l', 'o' });
      out.writeObject(new byte[] { 'W', 'o', 'r', 'l', 'd' });
    } finally {
      out.close();
    }
  }

}

Here's receiving:

import java.io.*;
import java.util.*;

public class Server {

  public static void main(String[] args) throws IOException, ClassNotFoundException {
    // write string
    ObjectInputStream in = new ObjectInputStream(
      new BufferedInputStream(
        new FileInputStream("test-string.data")));
    try {
      Object o = null;
      while ((o = in.readObject()) != null) {
        System.out.printf("Class: %s, toString: %s\n", o.getClass(), o.toString());
      }
    } catch (EOFException e) {
      // finished
    } finally {
      in.close();
    }
    // write byte arrays
    in = new ObjectInputStream(
      new BufferedInputStream(
        new FileInputStream("test-byteArrays.data")));
    try {
      Object o = null;
      while ((o = in.readObject()) != null) {
        System.out.printf("Class: %s, toString: %s\n", o.getClass(), o.toString());
      }
    } catch (EOFException e) {
      // finished
    } finally {
      in.close();
    }
  }

}

Upvotes: 2

G_H
G_H

Reputation: 12009

What you're doing is sending raw data over a socket. That's all you have: a stream of bytes. In order to make sure the receiving end can understand what part belongs with what file, and the type of this file, you'll need to come up with a way to encode this into the stream of bytes in such a way that the actual data isn't disturbed and both sender/receiver "understand" this structure. This is the sort of thing known as a protocol.

Coming up with your own protocol can be useful in some situations, but know that it can be very complex based on what you want to achieve. Most likely a protocol already exists that is well suited to your needs. You could use HTTP with the MIME type indicated in the header fields. This would let you figure out the file type and, in the case of text, the encoding. FTP is suitable for file transfers, and the extension of the file name could be used to detect its type. SOAP allows you to send complex data structures in a way that is independent on the client's or server's implementation languages.

TL;DR version: don't reinvent the wheel, search around for what exists out there to suit your needs. Most likely, the suitable protocol has support in Java out-of-the-box or via a third-party library. Apache's Commons Net could help you here.

Upvotes: 1

claesv
claesv

Reputation: 2113

There's no automatic handling of data boundaries. The server code has no way of knowing where one file/message ends and the other begins. You'll have to come up with your own protocol.

Upvotes: 2

Related Questions