1

Currently I am working on a server/client application which sends data using java with Runnable and threads. The problem is that the client is sending the data and when the server starts to read it the client has already finished and closed the connection which on the server side only a partially of the data is arrived, can they be setup to be synchronized?

this is the client:

private void ConnectionToServer(final String ipAddress, final int Port) {
   final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(10);

   Runnable serverTask = new Runnable() {
        @Override
        public void run() {
            try {
                socket = new Socket(ipAddress, Port);

                bos = new BufferedOutputStream(socket.getOutputStream());
                dos = new DataOutputStream(socket.getOutputStream());

                File f = new File("C:/Users/lukeLaptop/Downloads/RemoveWAT22.zip");

                String data = f.getName()+f.length();
                byte[] b = data.getBytes();

                sendBytes(b, 0, b.length);


                dos.flush();
                bos.flush();

                bis.close();

                dos.close();

                //clientProcessingPool.submit(new ServerTask(socket));
           } catch (IOException ex) {
               Logger.getLogger(ClientClass.class.getName()).log(Level.SEVERE, null, ex);           } finally {

           }

       }
    };

    Thread serverThread = new Thread(serverTask);
    serverThread.start();

    public void sendBytes(byte[] myByteArray, int start, int len) throws IOException {
    if (len < 0) {
        throw new IllegalArgumentException("Negative length not allowed");
    }
    if (start < 0 || start >= myByteArray.length) {
        throw new IndexOutOfBoundsException("Out of bounds: " + start);
    }
// Other checks if needed.

// May be better to save the streams in the support class;
    // just like the socket variable.
    OutputStream out = socket.getOutputStream();
    DataOutputStream dos = new DataOutputStream(out);

    dos.writeInt(len);
    if (len > 0) {
        dos.write(myByteArray, start, len);
    }
}

server code:

   private void acceptConnection() {

    try {

        final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(10);

        Runnable serverTask = new Runnable() {
            @Override
            public void run() {
                try {
                    ServerSocket server = new ServerSocket(8080);

                    while (true) {
                        socket = server.accept();

                        System.out.println("Got a client !");

                        bis = new BufferedInputStream(socket.getInputStream());

                        dis = new DataInputStream(socket.getInputStream());

                        String data = readBytes().toString();

                        System.out.println(data);


                        bos.close();

                        dis.close();

                        //clientProcessingPool.submit(new ClientTask(socket));
                    }
                } catch (IOException ex) {
                    System.out.println(ex.getMessage());
                }
            }
        };
        Thread serverThread = new Thread(serverTask);
        serverThread.start();

    } catch (Exception io) {

        io.printStackTrace();

    }

}

public byte[] readBytes() throws IOException {
    // Again, probably better to store these objects references in the support class
    InputStream in = socket.getInputStream();
    DataInputStream dis = new DataInputStream(in);

    int len = dis.readInt();
    byte[] data = new byte[len];
    if (len > 0) {
        dis.readFully(data);
    }
    return data;
}
3
  • why do you use sendBytes() instead of bos.write()? Commented Feb 18, 2014 at 10:53
  • I have tried it that way also the same result it seams that the data is not all passed Commented Feb 18, 2014 at 11:14
  • how do you know that it is not all passed? Did you compare this string f.getName()+f.length(); with the one you receive at server? What's the difference? Commented Feb 18, 2014 at 11:48

1 Answer 1

8

You mixed up many things:

  1. Variables start most of the time with a lowercase letter, e.g. int port, int ipAddress
  2. Classes start with a uppercase letter, e.g. Client, Server
  3. only open one Data*stream on a socket. new DataInputStream(socket.getInputStream()) or new BufferedInputStream(socket.getInputStream()), but not both
  4. If you need both, chain them: new DataInputStream(new BufferedInputStream(socket.getInputStream()));
  5. KISS (Keep it short & simple)
  6. If you use a DataInputStream, then use the given functionality of sending objects and primitives, e.g. sendUTF(), sendInt(), sendShort(), and so on...
  7. Name your vars right: servertask is a client thread? no
  8. Move long anonymous classes to a new class
  9. Don't use port 8080, this port is used for many other application and will cause problems

example code regarding your example an my advices:

Server

public class Server implements Runnable {
    private void acceptConnection() {
            Thread serverThread = new Thread(this);
            serverThread.start();
    }

    @Override
    public void run() {
        try {
            ServerSocket server = new ServerSocket(8081);

            while (true) {
                Socket socket = server.accept();
                System.out.println("Got a client !");

                // either open the datainputstream directly
                DataInputStream dis = new DataInputStream(socket.getInputStream());
                // or chain them, but do not open two different streams:
                // DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));

                // Your DataStream allows you to read/write objects, use it!
                String data = dis.readUTF();
                System.out.println(data);

                dis.close();
                // in case you have a bufferedInputStream inside of Datainputstream:
                // you do not have to close the bufferedstream
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new Server().acceptConnection();
    }
}

description:

  1. main: create a new Server Object, which is a Runnable
  2. acceptConnections: create a Thread
  3. run:
    1. open a Serversocket
    2. wait for a connection
    3. open exactly one stream
    4. read the Data
    5. close the stream and wait for next connection

Client

public class Client {
    private static void sendToServer(String ipAddress, int port) throws UnknownHostException, IOException {
        Socket socket = new Socket(ipAddress, port);

        // same here, only open one stream
        DataOutputStream dos = new DataOutputStream(socket.getOutputStream());

        File f = new File("C:/Users/lukeLaptop/Downloads/RemoveWAT22.zip");
        String data = f.getName()+f.length();

        dos.writeUTF(data);

        dos.flush();
        dos.close();    
    }

    public static void main(String[] args) throws UnknownHostException, IOException {
        Client.sendToServer("localhost", 8081);
    }
}

description (This one is straight forward):

  1. open socket
  2. open DataStream
  3. send Data
  4. flush and close
Sign up to request clarification or add additional context in comments.

1 Comment

thanks that was quite informative actually, this is my first time dealing with sockets so it was quite help full thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.