简体   繁体   中英

TCP client and server

I'm working on a project which expects a TCP client and Server, where server echoes the message back to client. Following is from the assignment:

The server application shall:

  1. Listen for TCP connections on a well known IP address and port
  2. Accept connections initiated on that port
  3. Receive messages from the client and echo them back
  4. Continue to do this until the client drops the connection.

The client application shall:

  1. Establish a connection with the server at its well known IP address and port
  2. Send messages in an asynchronous manner to the server. The format of the message is of your choice; however, it must contain enough information in order for it to be recognized on its return from the server.

I have completed the coding for Server, and this is what i've come up with for the client.

My questions:

  • What does it mean that Server listens for TCP connections on a well known IP and Port In my implementation, i've used ServerSocket which accepts the port server listens on. Did i interpret it correctly?

  • In my current implementation of TCPClient, client sends messages to Server, but the println() seems to be a blocking call, which makes it Synchronous. What can i do to make my client asynchronous?

For brevity, I havent added the code of TCPServer, let me know if it is needed

UPDATE* * Based on the feedback, i have modified by TCPClient class. After receiving client request, i spawn two threads ReceiveMessage and SendMessage. Doing that gives me following exception:

[Client] Message sent: Message from Client 97
[Client] Message sent: Message from Client 98
[Client] Message sent: Message from Client 99
[Client] Done Sending all the messages
java.net.SocketException: Socket closed
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.read(SocketInputStream.java:129)
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
    at java.io.InputStreamReader.read(InputStreamReader.java:167)
    at java.io.BufferedReader.fill(BufferedReader.java:136)
    at java.io.BufferedReader.readLine(BufferedReader.java:299)
    at java.io.BufferedReader.readLine(BufferedReader.java:362)
    at org.chanders.client.ReceiveMessage.run(ReceiveMessage.java:18)
    at java.lang.Thread.run(Thread.java:680)

Following is the new Client Code:

public class TCPClient {
    Socket clientSocket = null;
    OutputStream out = null;
    BufferedReader in = null;
    String message = "Hello from Client";
    int messagecount = 100;

    // server credentials
    private static final String SERVER_ADDRESS = "localhost";
    private static final int SERVER_PORT = 50001;

    protected void execute() {
        try {
            clientSocket = new Socket(SERVER_ADDRESS, SERVER_PORT);
            Thread send = new Thread(new SendMessage(clientSocket.getOutputStream()));
            Thread receive = new Thread(new ReceiveMessage(clientSocket.getInputStream()));

            send.start();
            receive.start();

            //For server to wait until send and receive threads finish
            send.join();
            receive.join();

        } catch (UnknownHostException uhe) {
            System.err.println("Couldnt find host:  "  + SERVER_ADDRESS);
            uhe.printStackTrace();
            System.exit(-1);

        }catch(IOException ioe) {
            System.err.println("Couldnt get I/O:  "  + SERVER_ADDRESS);
            ioe.printStackTrace();
            System.exit(-1);

        }catch(InterruptedException ie) {
            System.err.println("Thread.join failed:  ");
            ie.printStackTrace();
            System.exit(-1);
        }
        finally {
            //cleanup();
        }
    }

    private void cleanup() {
        try {
            clientSocket.close();
        }catch(Exception e) {
            e.printStackTrace();
            System.exit(-1);
        }
    }

    public static void main(String[] args) {
        TCPClient client = new TCPClient();
        client.execute();
    }

public class SendMessage implements Runnable {
    OutputStream out = null;
    String message = "Message from Client";
    int messageCount = 100;

    public SendMessage(OutputStream out) {
        this.out = out;
    }

    public void run() {
        PrintWriter writer = new PrintWriter(out);
        try {

            for (int i = 0; i < messageCount; i++) {
                String m = message + " " + i;
                writer.println(m);
                System.out.println("[Client] Message sent: " + m);
            }
            System.out.println("[Client] Done Sending all the messages");

        } catch (Exception e) {
            e.printStackTrace();
            System.exit(-1);
        } finally {
            cleanup();
        }

    }
    private void cleanup() {
        try {
            out.close();
        }catch(Exception e) {
            e.printStackTrace();
            System.exit(-1);
        }
    }
}

public class ReceiveMessage implements Runnable {
    InputStream in = null;
    String message;

    public ReceiveMessage(InputStream in) {
        this.in = in;
    }

    public void run() {
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        try {

            while ((message = reader.readLine()) != null) {

                System.out.println("[Client] Received message from Server: "
                        + message);
            }

            System.out.println("[Client] Done Receiving messages from Server");

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            cleanup();
        }

    }
    private void cleanup() {
        try {
            in.close();
        }catch(Exception e) {
            e.printStackTrace();
            System.exit(-1);
        }
    }
}

In this context, Asynchronous probably doesn't mean that you can't use println, but that the client must be able to recevie messages while it's sending new ones. The client should create the socket and then create two threads, one to send messages and the other to recive and print them.

Update

To avoid the exception, use clientSocket.shutdownOutput() instead of closing the output stream. You could move the send code back to the main thread and keep a separate thread for the receive code or call shutdownOutput() after joining the send thread. Whatever works better for you.

Use a separate thread for each client. When you write something, in the server end , there must be a method which accepts the string. Otherwise it will be blocking. Paste your server code.

Well known ports are port numbers that have been specifically designated for particular protocols, for example 80 is for HTTP and 443 is for HTTPS. Are you meant to be implementing a particular protocol? If you are I would suggest you use the port number for that protocol. Wikipedia has a list of well known port numbers here: http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers

If this is a professional assignment (as opposed to a some homework) then I would strongly recommend the Netty Server , which is basically a NIO client server framework. It significantly simplifies/streamlines the development of this sort.

Make sure to check their documentation as it provides examples implementing exactly the server/client functionality stated in the question.

If this is a homework then this example should provide all necessary details. Please also check Oracle resources .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM