0

I have a socket client sending text to a socket server but the ReadLine doesnt seem to wait to receive a line before proceeding. Here is the of the server receiving the text:

public void run() {

        try {

            serveurSocket = new ServerSocket(PORT_ID);  
            connexionSocket = serveurSocket.accept();


            BufferedReader reader = new BufferedReader(new InputStreamReader(connexionSocket.getInputStream()));
            PrintWriter writer = new PrintWriter(connexionSocket.getOutputStream(), true);

            messageRecu = "";
            while (true) {
                messageRecu = reader.readLine();
                messageRecu = messageRecu.toUpperCase();
                writer.println(messageRecu);
            }

            //reader.close();
            //writer.close();


        } catch (IOException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }

    }

After establishing the socket between client and server, the execution halts at reader.readLine until I send manually a string thru the socket. Which is normal and wanted. Codes resumes and its fine until its loops back to reader.ReadLine() where it will read a "null" line instead of waiting for input from the socket like it did the first time... this will obviously mess up the next command to uppercase. So how can I fix this?

EDIT: I'll add the client side if that can help understand.

public class ClientSocket {

    private Socket clientSocket;

    public boolean isClosed() { return clientSocket.isClosed(); }

    public boolean connectToSocket (String ip, int port) {

        try {
            clientSocket = new Socket(ip, port);
            return true;
            } 
        catch (IOException e) { 
            System.out.println(e); 
            return false;
        }

    }

    public String sendToServer(String messageClient) {

        String messageRecu = "";

        try {

            BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            PrintWriter writer = new PrintWriter(clientSocket.getOutputStream(), true);

            writer.println(messageClient);
            messageRecu = reader.readLine();

            reader.close();
            writer.close();

            return messageRecu;

        } 
        catch (IOException e) {

            System.out.println(e.getMessage());
            e.printStackTrace();

            return messageRecu;

        }

    }

}

A button press will call "connectTosocket" to initiate the socket. A second button when pressed will send the content of a textfield using "sendToServer".

Server does receive the message and return it capitalized but I wish for the socket to remain open with the server and if I send an other string for the same sequence to happen. Not even sure it can be done :(

JulioQc
  • 310
  • 1
  • 4
  • 20
  • 1
    When `null` is returned, the stream has terminated. It's time to close your BufferedReader, not to keep reading. The problem is in your server code, and you need to see why it's terminating the stream when you don't expect it to. Also get rid of the `while (true)` in your client as that's dangerous code. – Hovercraft Full Of Eels Jul 15 '15 at 02:55

2 Answers2

2

According to the documentation of BufferedReader#readLine, a null is returned if the end of stream has been reached.

Change your reading loop to :

while ((messageRecu = reader.readLine()) != null) {
    messageRecu = messageRecu.toUpperCase();
    writer.println(messageRecu);
}
//Get out of the loop when the end of stream is reached.

As per Reading from and Writing to a Socket chapter of the Java tutorial.

As a side note, while(true) loops are not really appreciated.

Community
  • 1
  • 1
Jean-François Savard
  • 20,626
  • 7
  • 49
  • 76
  • 2
    Finally, a decent answer. 1+ – Hovercraft Full Of Eels Jul 15 '15 at 02:56
  • 1
    @Ouney: if the stream is still open, then null shouldn't be sent. We don't know what his server code looks like, but it's terminating the stream, so it's likely doing something wrong. the solution is not to try to program a kludge in the client. – Hovercraft Full Of Eels Jul 15 '15 at 02:58
  • This will not work as the first `null` that'll be sent will close the connection and no new requests will be able accepted. – Nir Alfasi Jul 15 '15 at 03:01
  • @Ouney The stream should not be closed until the communication between client-server is done. – Jean-François Savard Jul 15 '15 at 03:04
  • If i see alfasin implementation above.....the socket is being closed after the while loop is done (when the first null is received) which mean end of communication, right/ – Ouney Jul 15 '15 at 03:07
  • 1
    @Ouney The server *can't* send any more data. It has closed the connection. – user207421 Jul 15 '15 at 03:09
  • 1
    @alfasin A null cannot possibly *be* sent, and there is nothing in this code that prevents new connections from being accepted. – user207421 Jul 15 '15 at 03:09
  • @Ouney Yes, if the stream is ended, there is no point to keep the communication open. – Jean-François Savard Jul 15 '15 at 03:10
  • I wrote that a `null` will be sent, it's not being "actively" sent (it is being received thought) and it just signals the end of connection, I consider it a "wording" issue since I wasn't careful enough in the distinction of send/receive - I sometimes write quickly what's on my mind assuming it's clear enough to understand but I humbly accept the correction cause after all definitions are *very* important. As for your claim that nothing "prevents new connections from being accepted" - true, but I don't see it implemented in the code above... – Nir Alfasi Jul 15 '15 at 03:27
0

The "null" signals for end of connection from the client side - which is why the connection disconnects. If you want to support multiple requests, you should run a new ServerSocket.accept() each time and wait for a new client to connect.

KKMultiServer class:

import java.net.*;
import java.io.*;


public class KKMultiServer {
    public static void main(String[] args) throws IOException {

    if (args.length != 1) {
        System.err.println("Usage: java KKMultiServer <port number>");
        System.exit(1);
    }

        int portNumber = Integer.parseInt(args[0]);
        boolean listening = true;

        try (ServerSocket serverSocket = new ServerSocket(portNumber)) { 
            while (listening) {
                new KKMultiServerThread(serverSocket.accept()).start();
            }
        } catch (IOException e) {
            System.err.println("Could not listen on port " + portNumber);
            System.exit(-1);
        }
    }
}

KKMultiServerThread class:

import java.net.*;
import java.io.*;

public class KKMultiServerThread extends Thread {
    private Socket socket = null;

    public KKMultiServerThread(Socket socket) {
        super("KKMultiServerThread");
        this.socket = socket;
    }

    public void run() {

        try (
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            BufferedReader in = new BufferedReader(
                new InputStreamReader(
                    socket.getInputStream()));
        ) {
            String inputLine, outputLine;
            KnockKnockProtocol kkp = new KnockKnockProtocol();
            outputLine = kkp.processInput(null);
            out.println(outputLine);

            while ((inputLine = in.readLine()) != null) {
                outputLine = kkp.processInput(inputLine);
                out.println(outputLine);
                if (outputLine.equals("Bye"))
                    break;
            }
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

You can read more about sockets in Oracle tutorials

Nir Alfasi
  • 53,191
  • 11
  • 86
  • 129