0

this are my first java steps with a socket connection. I like to code a tcp client that connects to a server and read all data that the server will ever send. Each message from the server will be terminated by 0x00.

First question: How can i read this variable message length?

Secont question: if the user enters text via the keyboard this text should be send to the server, while i am receiving. But how can i send data while i am reading from the server?

This is my code till now:

import java.io.*;

 public class Client {
     public static void main(String[] args) {
    Client client = new Client();
    try {
        client.test();
    } catch (IOException e) {
        e.printStackTrace();
    }
     }
     void test() throws IOException {
    String ip = "127.0.0.1"; // localhost
    int port = 12345;
    java.net.Socket socket = new java.net.Socket(ip,port); // verbindet sich mit Server
    String zuSendendeNachricht = "Hello World0x00";
    schreibeNachricht(socket, zuSendendeNachricht);
    while (true){
        String empfangeneNachricht = leseNachricht(socket);
        System.out.println(empfangeneNachricht);
        }
     }
     void schreibeNachricht(java.net.Socket socket, String nachricht) throws IOException {
     PrintWriter printWriter =
        new PrintWriter(
        new OutputStreamWriter(
            socket.getOutputStream()));
    printWriter.print(nachricht);
    printWriter.flush();
    }
    String leseNachricht(java.net.Socket socket) throws IOException {
    BufferedReader bufferedReader =
        new BufferedReader(
        new InputStreamReader(
            socket.getInputStream()));
    char[] buffer = new char[200];
        int anzahlZeichen = bufferedReader.read(buffer, 0, 200); // blockiert bis Nachricht empfangen
        String nachricht = new String(buffer, 0, anzahlZeichen);
        System.out.println(nachricht);
    }
 }

And how can i read a variable message length

1
  • Are you reading binary content or Strings or anything else ? You don't need to know message length as read() method will tell you when reading has ended Commented Jan 5, 2015 at 22:45

2 Answers 2

1

First question: How can i read this variable message length?

Just read the incoming data with size of 1 byte and check every byte on 0x00.

Secont question: if the user enters text via the keyboard this text should be send to the server, while i am receiving. But how can i send data while i am reading from the server?

Start two independent threads. One for reading and one for writing. Pseudo code:

Thread readingThread = new Thread(new Runnable() {
  @Override
  public void run() {
    //do reading here...
  }
});
readingThread.start();

Thread writingThread = new Thread(new Runnable() {
  @Override
  public void run() {
    //do writing here...
  }
});
writingThread.start();

Find a working example below for reading every byte and check on 0x00. There are no threads used here.

Content of Client.java:

package tcpserverclient;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Client {

    private static final Logger LOG = Logger.getLogger(Client.class.getName());

    private String getData(InputStream stream2server) {
        BufferedInputStream inputStream = new BufferedInputStream(stream2server);

        StringBuilder incomingData = new StringBuilder("");
        try {
            int c;
            LOG.info("reading incoming data...");
            while ((c = inputStream.read()) != -1) {
                if (c == 0) {
                    break;
                } else {
                    incomingData.append((char) c);
                    System.out.print((char) c);
                }
            }
            LOG.info("\ndata complete.");
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        return incomingData.toString();
    }

    private void startListen(int port) {
        try {
            ServerSocket serverSocket = new ServerSocket(port);
            while (true) {
                LOG.info("\nListening on port " + port);
                Socket socket = serverSocket.accept();
                LOG.info("incoming call...");

                InputStream incoming = socket.getInputStream();
                OutputStream outgoing = socket.getOutputStream();
                String data = getData(incoming);
                LOG.info(data);

                outgoing.close();
                incoming.close();
                socket.close();
            }

        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new Client().startListen(9999);
    }
}

Content of Server.java:

package tcpserverclient;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class Server {

    public void sendCommand(String ip, int port, String cmd) {
        try {
            Socket socket = new Socket(ip, port);
            InputStream fromServer = socket.getInputStream();
            OutputStream toServer = socket.getOutputStream();
            socket.setSoTimeout(0);

            byte[] ba = cmd.getBytes();
            byte[] ba0 = new byte[ba.length + 1];
            System.arraycopy(ba, 0, ba0, 0, ba.length);
            ba0[ba.length] = 0;

            toServer.write(ba0);

            fromServer.close();
            toServer.close();
            socket.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new Server().sendCommand("127.0.0.1", 9999, "Hal, can you read me?");
    }
}

Start the Client.java first then the Server.java. Output is something like this:

run:
Jan 06, 2015 9:19:42 AM tcpserverclient.Client startListen
Information: 
Listening on port 9999
Jan 06, 2015 9:19:44 AM tcpserverclient.Client startListen
Information: incoming call...
Jan 06, 2015 9:19:44 AM tcpserverclient.Client getData
Information: reading incoming data...
Jan 06, 2015 9:19:44 AM tcpserverclient.Client getData
Information: 
data complete.
Jan 06, 2015 9:19:44 AM tcpserverclient.Client startListen
Information: Hal, can you read me?
Jan 06, 2015 9:19:44 AM tcpserverclient.Client startListen
Information: 
Listening on port 9999
Hal, can you read me?
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your help. Do you have an example how to: "Just read the incoming data with size of 1 byte and check every byte on 0x00" Thanks a lot!
See my edit above for how to read byte after byte. I created a byte array on server side and added a 0 at the end.
0

Are you able to modify the server to use line endings to terminate messages instead of "0x00"? If so then you will be able to use readLine instead of read with the bufferedReader which will allow you to read variable messages.

You don't need to initialise your bufferedReader every time the loop runs, you can initialise it at the start and just call the read/write methods in the loop.

To write while reading, you need to have a BufferedReader which is reading from stdin, then you need to read from it and write to your output stream all within the while loop which I mentioned before.

This page has code examples and an explanation for all of this: http://docs.oracle.com/javase/tutorial/networking/sockets/readingWriting.html

Comments

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.