2022Java learning notes 79 (network programming: TCP communication, TCP communication: multiple client messages [key points], tracking client online and offline functions, thread pool optimization)
1, TCP communication quick start
TCP protocol review:
1. TCP is a connection oriented, secure and reliable data transmission protocol
2. Before transmission, the "three-time handshake" mode is adopted for point-to-point communication, which is reliable
3. A large amount of data can be transmitted in the connection
Constructors and common API s
2, TCP client sends message
Sample code
package com.zcl.d12_tcpDaemo; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.net.Socket; /* // Objective: to complete the client development of socket network programming entry case, with the function of one sending and one receiving */ public class ColientDemo { public static void main(String[] args) { System.out.println("-------- Client started successfully --------"); try { // 1. Create socket communication pipeline to request the connection of the server 1 /** * Parameter 1: IP address of the server * Parameter 2: server port */ Socket socket = new Socket("127.0.0.1",7777); // 2. Get a byte output stream from the socket channel, which is responsible for sending data OutputStream ops = socket.getOutputStream(); // Wrap the low-level byte stream into a print stream PrintStream ps = new PrintStream(ops); // send message ps.println("I invite you"); // It must be a one line message ps.flush(); // Do not close the print stream. You need to send a close message to close it } catch (Exception e) { e.printStackTrace(); } } }
3, Server code writing
Sample code
package com.zcl.d12_tcpDaemo; import java.io.*; import java.net.ServerSocket; import java.net.Socket; /* Objective: to develop the server of socket network programming entry code to receive messages */ public class ServerDemo { public static void main(String[] args) { System.out.println("-------- The server is started successfully --------"); try { // 1. Registration server ServerSocket serverSocket = new ServerSocket(7777); // 2. The accept method must be called to wait for receiving the socket connection request from the client and establish the socket communication pipeline Socket socket = serverSocket.accept(); // 3. Get a byte input from the socket communication pipeline InputStream is = socket.getInputStream(); // 4. Convert the character input stream packet into a cached character input stream for message reception BufferedReader br = new BufferedReader(new InputStreamReader(is)); // 5. Read messages by line according to cache byte input stream String msg; if ((msg = br.readLine()) != null) { System.out.println(socket.getRemoteSocketAddress()+"Said:"+msg); } } catch (Exception e) { e.printStackTrace(); } } }
It is necessary to strictly abide by the principle of one sending and one receiving. If the client does not use one line of message to send, and the server uses to receive one line of data, an error will be reported, because the client does not send one line of data, and the server will receive incomplete messages
If the client sends only one line of data, and the server uses the loop while() to receive data, it will also report an error, because the client has completed a message sending, has been turned off, and the server is still receiving data
3, TCP communication: multiple sending and multiple receiving cases
On the basis of the above code, add repeated cycles to the client and server respectively
Client code modification
while (true) { System.out.println("Please enter the message to send:"); String msg = sc.nextLine(); // send message ps.println(msg); // It must be a one line message ps.flush(); // Refresh }
Server code modification
while ((msg = br.readLine()) != null) { System.out.println(socket.getRemoteSocketAddress()+"Said:"+msg); }
Now the written server can receive messages from one client at the same time. The reason is that the current server is single threaded and can only process messages from one client at a time
4, Receive multiple client messages at the same time [key]
Reference multithreading
Implementation code
1. Don't move the client code
2. Modify the code of the server
package com.zcl.d13_socket4; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; /* Objective: to develop the server of socket network programming entry code to realize that the server can receive multiple client messages at the same time */ public class ServerDemo { public static void main(String[] args) { System.out.println("-------- The server is started successfully --------"); try { // 1. Registration server ServerSocket serverSocket = new ServerSocket(7777); while (true) { // 2. After receiving a socket pipe from a client, an independent sub thread is responsible for reading the message Socket socket = serverSocket.accept(); // 3. Start creating independent thread processing socket new ServerReaderThread(socket).start(); } } catch (Exception e) { e.printStackTrace(); } } }
3. Create a multi-threaded ServerReaderThread class to implement the Thread class
package com.zcl.d13_socket4; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.Socket; public class ServerReaderThread extends Thread{ private Socket socket; public ServerReaderThread(Socket socket){ this.socket = socket; } @Override public void run() { try { // 3. Get a byte input from the socket communication pipeline InputStream is = socket.getInputStream(); // 4. Convert the character input stream packet into a cached character input stream for message reception BufferedReader br = new BufferedReader(new InputStreamReader(is)); // 5. Read messages by line according to cache byte input stream String msg; while ((msg = br.readLine()) != null) { System.out.println(socket.getRemoteSocketAddress()+"Said:"+msg); } } catch (Exception e) { e.printStackTrace(); } } }
The client can receive more messages
About how to track the online and offline functions of the client
1. In the while loop of the server, you can know which client is online through the IP address of the socket
//Judge who is online on the system out. Println (socket. Getremotesocketaddress() + "he's online");
2. In the defined ServerReaderThread multithread class, the final IP address in the capture catch is judged as offline. If the client reports an error, the server will report an error to that client
// User offline notification System.out.println(socket.getRemoteSocketAddress() + "He's offline");
In the defined ServerReaderThread multithread class
5, TCP communication: thread pool optimization
1. The client code does not need to be moved
2. Modify server code
package com.zcl.d14_scoket5; import com.zcl.d13_socket4.ServerReaderThread; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.*; /* Objective: to develop the server of socket network programming entry code to realize that the server can receive multiple client messages at the same time */ public class ServerDemo { // Use static variables to remember a thread pool object private static ExecutorService pool = new ThreadPoolExecutor(3,5,6, TimeUnit.SECONDS,new ArrayBlockingQueue<>(2),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy()); public static void main(String[] args) { System.out.println("-------- The server is started successfully --------"); try { // 1. Registration server ServerSocket serverSocket = new ServerSocket(6666); while (true) { // 2. After receiving a socket pipe from a client, an independent sub thread is responsible for reading the message Socket socket = serverSocket.accept(); // Judge who is online System.out.println(socket.getRemoteSocketAddress()+"He's online"); // The task object is responsible for reading messages Runnable target = new ServerReaderRunnable(socket); // Submit route pool queue pool.execute(target); } } catch (Exception e) { e.printStackTrace(); } } }
The ExecutorService thread pool object is added. The information initiated by the client is submitted through the thread pool and queued in the thread pool
3. Create a ServerReaderRunnable task object to implement the Runnable interface
The constructor needs to be rewritten to receive the object sent by the client
package com.zcl.d14_scoket5; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.Socket; public class ServerReaderRunnable implements Runnable{ // Receiving object private Socket socket; // A parameterized constructor receives an object public ServerReaderRunnable(Socket socket) { this.socket = socket; } @Override public void run() { try { // 3. Get a byte input from the socket communication pipeline InputStream is = socket.getInputStream(); // 4. Convert the character input stream packet into a cached character input stream for message reception BufferedReader br = new BufferedReader(new InputStreamReader(is)); // 5. Read messages by line according to cache byte input stream String msg; while ((msg = br.readLine()) != null) { System.out.println(socket.getRemoteSocketAddress()+"Said:"+msg); } } catch (Exception e) { // e.printStackTrace(); // User offline notification System.out.println(socket.getRemoteSocketAddress() + "He's offline"); } } }
What are the advantages of using thread pools
1. The server can reuse the thread pool to process multiple clients, which can avoid system paralysis
2. It is suitable for scenarios where the communication time of the client is short