NewGuyInJava
NewGuyInJava

Reputation: 216

Java Simple EchoServer won't work

I read through SO a lot and I found many examples which were doing what I am trying to do. But I just can't find the issue in my code at all. May be I just need a fresh set of eyes to look at my code. So with risk of being flagged for duplicate thread here is goes. I have a simple Java code. It opens a port. Connects a socket to that. gets the inputstream and outputstream. Puts some text to output stream and inputstream tries to read the text. When the mehtod for readLine is executed it does not return back to the code. It just keeps running and never comes back to main method.

import java.net.*;
import java.io.*;
import java.io.ObjectInputStream.GetField;

public class echoserver {

public static void main(String[] args) {
    // TODO Auto-generated method stub
    String hostName = "127.0.0.1";
    //      InetAddress.getLocalHost()
    int portNumber = 5000;
    ServerSocket ss = null;
    Socket echoSocket = null;


    try {
        ss = new ServerSocket(portNumber);
        echoSocket = new Socket(hostName, portNumber);
//          echoSocket = ss.accept();
        System.out.println("open");
        System.out.println(echoSocket.isBound());

        PrintWriter writer = new PrintWriter(echoSocket.getOutputStream());
        for (int i = 0; i < 100; i++) {
            writer.print("test String");    
        }

        writer.flush();
//          writer.close();

        System.out.println("inputstream read");
       DataInputStream is = new DataInputStream(echoSocket.getInputStream());
       String fromStream = is.readLine();
       System.out.println(fromStream);

       System.out.println("bufferreader read");

        BufferedReader reader = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
        String fromReader = reader.readLine();

        System.out.println(fromReader);

    } catch (UnknownHostException  ex1) {
        // TODO Auto-generated catch block
        System.out.println("EX1");
        ex1.printStackTrace();
    }

    catch (IOException ex2) {
        // TODO: handle exception
        System.out.println("EX2");
        ex2.printStackTrace();
    }

    finally {
        try {
            echoSocket.close();
            ss.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }



}

}

EDIT : Updated Code below... The only issue in this code is that while loop in Server.Run never ends. I looked for some other attributes (I remember something like isTextAvailable) but could not find it. The idea behind the code is to convert it into a chat client. needless to say its a struggle !

EDIT 2: I found the the issue. I never closed the socket from writer end so the listner kept on listening ! Thanks for help everyone !

clientsocket.close();

Added one line and it worked!

import java.net.*;
import java.io.*;
import java.io.ObjectInputStream.GetField;
import java.util.*;

public class echoserver {



static echoserver echo;

public static class Client implements Runnable {

    Socket clientsocket;
    String hostName = "127.0.0.1";
    int portNumber = 5000;
    static int onesleep = 0;

    public void run(){ 


        System.out.println("Client Run  " + new Date());

        try {
            clientsocket = new Socket(hostName,portNumber);
            PrintWriter writer = new PrintWriter(clientsocket.getOutputStream());

            for (int i = 0; i < 10; i++) {
                writer.println("test String   " + i );  
            }

            writer.flush();
                            clientsocket.close();
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }



    }
}

public class Server implements Runnable {

    public void run(){

        System.out.println("Server Run" + new Date());
        int portNumber = 5000;
        ServerSocket ss = null;
        Socket serversocket = null;
        InputStreamReader streamReader; 

        try {
            ss = new ServerSocket(portNumber);
            serversocket = ss.accept();

            System.out.println("bufferreader read  " + new Date());

            streamReader = new InputStreamReader(serversocket.getInputStream());
            BufferedReader reader = new BufferedReader(streamReader);
            String fromReader;

            System.out.println(reader.ready());
            System.out.println(reader.readLine());



            while ((fromReader = reader.readLine()) != null) {
                System.out.println(fromReader);

            }

            System.out.println("After While in Server Run");


        } catch (IOException ex_server) {
            // TODO Auto-generated catch block
            System.out.println("Server Run Error    " + new Date());
            ex_server.printStackTrace();

        }
          finally {
              try {
                serversocket.close();
                  ss.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

          }
        System.out.println("open" + new Date());
        System.out.println(serversocket.isBound());


    }
}


public void go(){

    Server server = new Server();
    Thread serverThread = new Thread(server);
    serverThread.start();

    Client client = new Client();
    Thread clientThread = new Thread(client);
    clientThread.start();

}

public static void main(String[] args) {
    // TODO Auto-generated method stub

    echo = new echoserver();
    echo.go();





}

}

Upvotes: 3

Views: 657

Answers (2)

Paul Richter
Paul Richter

Reputation: 11072

I had prepared a version of this post earlier, but based on your last comment in the other answer, it seems you have already figured it out. I'll posting this anyways, in case it is of any help.

The broad answer is that your class, as you currently have it, effectively represents both the client-side AND server-side portions within the same thread / process. As you've seen, you're able to write your data to the outbound (or client-side) socket, but the server-side component never gets a chance to listen for incoming connections.

Consequently, when you attempt to read data from the inbound (or server-side) socket's input stream, nothing exists because nothing was received. The readline() method ultimately blocks until data is available, which is why your program seems to hold at that point. Additionally, like haifzhan said, creating a new socket using new Socket(...) doesn't establish the connection, all you have is a socket with nothing in the stream.

The ServerSocket#accept method what you need to use in order to listen for connections. This method will create the socket for you, from which you can attempt to read from its stream. Like haifzhan said, that method blocks until a connection is established, which is ultimately why it cannot function properly in a single-threaded environment.

To do this within the same application, you'll simply need to separate the components and run them in separate threads. Try something like the following:

public class EchoClient {

    public static void main(String[] args) throws InterruptedException {
        new Thread(new EchoServer()).start(); // start up the server thread

        String hostName = "localhost";
        int portNumber = 5000;

        try {
            Socket outboundSocket = new Socket(hostName, portNumber);

            System.out.println("Echo client is about to send data to the server...");

            PrintWriter writer = new PrintWriter(outboundSocket.getOutputStream());
            for (int i = 0; i < 100; i++) {
                writer.print("test String");
            }

            System.out.println("Data has been sent");

            writer.flush();
            outboundSocket.close();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

And the server component, which operates as a separate thread:

public class EchoServer implements Runnable {

    public void run(){
        try {
            ServerSocket ss = new ServerSocket(5000);
            System.out.println("Waiting for connection...");
            Socket inboundSocket = ss.accept();

            System.out.println("inputstream read");
            DataInputStream is = new DataInputStream(inboundSocket.getInputStream());

            BufferedReader reader = new BufferedReader(new InputStreamReader(is));

            String fromStream = reader.readLine();
            System.out.println(fromStream);

            System.out.println("bufferreader read");
            ss.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Upvotes: 4

Haifeng Zhang
Haifeng Zhang

Reputation: 31905

You did not connect to any client side socket...

From Writing the Server Side of a socket:

The accept method waits until a client starts up and requests a connection on the host and port of this server. When a connection is requested and successfully established, the accept method returns a new Socket object which is bound to the same local port and has its remote address and remote port set to that of the client. The server can communicate with the client over this new Socket and continue to listen for client connection requests on the original ServerSocket.

ss = new ServerSocket(portNumber);
echoSocket = new Socket(hostName, portNumber)
// echoSocket = ss.accept();

You should not use new Socket(host, port) to create a echoSocket, the ss.accept() is the correct way to establish the server client connection.

The reason it hangs because your code above(echoSocekt = ss.accept();) is not correct so the following will not be availalbe

DataInputStream is = new DataInputStream(echoSocket.getInputStream());

If you invoke is.available(), it will return 0 which means 0 bytes can be read from.

Read the link I provided, check EchoServer.java and EchoClient.java, and you will estiblish your own connection

Upvotes: 2

Related Questions