简体   繁体   English

TCP客户端和服务器

[英]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. 我正在一个需要TCP客户端和Server的项目上工作,在该项目中服务器将消息回显给客户端。 Following is from the assignment: 以下是作业的内容:

The server application shall: 服务器应用程序应:

  1. Listen for TCP connections on a well known IP address and port 在已知的IP地址和端口上侦听TCP连接
  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 通过众所周知的IP地址和端口与服务器建立连接
  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. 我已经完成了Server的编码,这就是我为客户端准备的。

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. 服务器侦听众所周知的IP和端口上的TCP连接是什么意思在我的实现中,我使用了ServerSocket来接受服务器侦听的端口。 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. 在我当前的TCPClient实现中,客户端将消息发送到服务器,但是println()似乎是一个阻塞调用,这使其成为“同步”。 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 为简便起见,我没有添加TCPServer的代码,请告知是否需要

UPDATE* * Based on the feedback, i have modified by TCPClient class. 更新* *根据反馈,我已经通过TCPClient类进行了修改。 After receiving client request, i spawn two threads ReceiveMessage and SendMessage. 收到客户端请求后,我产生了两个线程ReceiveMessage和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. 在这种情况下, Asynchronous可能并不意味着您不能使用println,而是客户端必须能够在发送新消息时接收消息。 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. 为避免该异常,请使用clientSocket.shutdownOutput()而不是关闭输出流。 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. 您可以将发送代码移回主线程,并为接收代码保留一个单独的线程,或者在加入发送线程之后调用shutdownOutput()。 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. 众所周知的端口是专门为特定协议指定的端口号,例如80用于HTTP,443用于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 Wikipedia在此处提供了众所周知的端口号列表: 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. 如果这是一项专业的工作(而不是做一些家庭作业),那么我强烈推荐Netty Server ,它基本上是一个NIO客户端服务器框架。 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 . 另请检查Oracle资源

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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