Directory
1. Network programming
2. Echo model (the server communicates with the client)
3. BIO processing model (realize multi-user access to the same server)
4. UDP program
1. Network programming
There are two communication models
C/S (Client/Server) is based on the client and the server, and the client and the server need to be implemented when implementing the code
B/S (Browser/Server) is based on Http web page and server side, only need to implement server side when implementing
2.Echo model (server and client communication)
The so-called Echo model refers to that the client sends a message to the server, the server receives the message and then sends the information received by the client back to the client. So you need to write two ports, one client and one server. Java can use the Socket class to implement the client (client) and ServerSocket class (server)
Both Socket and ServerSocket are based on TCP (connected, reliable transmission service)
Common methods of the Socket class (client):
Method | Description |
---|---|
public Socket(String host , int port) |
Create a socket, connect to the specified host name and port number |
public OutputStream getOutputStream() |
Returns the output stream of this socket, used to send data to the server, generally use PrintStream |
public InputStream getInputStream () |
Returns the input stream of this socket for receiving data from the server |
Common methods of the ServerSocket class (server side):
Method | Description |
---|---|
ServerSocket(int port) |
Create a server socket, bind to the specified port number |
Socket accept() |
Monitor and accept the connection request from the client, and return a new Socket object to communicate with the client |
void close() |
Close the server socket and stop listening to client connection requests |
Echo model implementation case code:
1. Server-side code implementation:
package Example1903; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; import java.util.Date; import java.util.Scanner; //Service-Terminal public class javaDemo { public static void main(String[] args) throws Exception{ Date date = new Date(); ServerSocket server = new ServerSocket(9999); System.out.println("Waiting for the client to run --------"); Socket client = server. accept(); // Set the input and output stream of the server to ensure that it can receive information and input information Scanner scanner = new Scanner(client. getInputStream()); PrintStream out = new PrintStream(client. getOutputStream()); // Receive information and pass information to out output stream boolean flag = true; scanner.useDelimiter("\\ "); while (flag){ if (scanner. hasNext()){ String value = scanner. next(). trim(); if ("byebye".equalsIgnoreCase(value)){ out.println("ByeBye"); flag = false; }else out.println(date + "[server] sent message:" + value); } } // close all services server. close(); client. close(); scanner. close(); out. close(); } }
2. Client code implementation:
package Example1904; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.Socket; import java.util.Date; import java.util.Scanner; //client public class javaDemo { // input information via keyboard private static final BufferedReader KEYBOARD_INPUT = new BufferedReader(new InputStreamReader(System.in)); public static String getString(String promp) throws Exception{ System.out.print(promp); String str = KEYBOARD_INPUT. readLine(); return str; } public static void main(String[] args) throws Exception { Date date = new Date(); Socket client = new Socket("localhost",9999); // Get the same input and output objects Scanner scanner = new Scanner(client. getInputStream()); PrintStream out = new PrintStream(client. getOutputStream()); scanner.useDelimiter("\\ ");//use delimiter boolean flag = true; while (flag){ String input = getString( date + "[Client] Please enter the information to be sent:").trim(); out.println(input);//Put the input content into the PrintStream stream if (scanner. hasNext()){ System.out.println(scanner.next()); } if ("byebye".equalsIgnoreCase(input)){ flag = false; } } } }
Server-side running results
Client running results:
Code flow:
The server starts and waits for connections: After the server starts, listen to the specified port (here 9999) through
ServerSocket
, and call theaccept
method to wait for the client to connect. Once a client is successfully connected, the server creates a new thread to handle communication with the client.The client connects to the server: the client connects to the specified server address (here
localhost
) and port number (here it is9999
) through theSocket
constructor code>).The client sends a message: the client obtains the message input by the user through the
getString
method, and sends the message to the server through theprintln
method ofPrintStream
.The server receives the message: the server reads the message sent by the client through the
next
method ofScanner
in its own thread.Server processing message: The server performs corresponding processing according to the received message, which can be parsing, judging, calculating and other operations on the message. In this example, the server simply sends the received message back to the client as-is.
The server returns a message: the server sends the processed message to the client through the
println
method ofPrintStream
.The client receives the message: the client reads the message returned by the server through the
next
method ofScanner
and prints it to the console.Repeat steps 3-7 until the client sends “byebye”, indicating the end of the communication.
Q&A:
Question 1: How do the two codes communicate?
First of all, the communication between the two processes must receive the corresponding port (computer network application layer knowledge) to communicate, and then the two codes share the input and output streams (it can be understood as two people using the same telephone line), the client The terminal outputs information to the server through its output stream out. The external input of the server is the input stream, that is, the output stream becomes the input stream of the server. The server receives the information of the client’s output stream through the scanner input stream. Similarly, the server also passes Its output stream is output to the client, and the client outputs the information when it receives the information
Question 2: The scanner.useDelimiter(“\\
“); useDelimiter method knows to set the delimiter, but does it have any effect when paired with “\\
“?
scanner.useDelimiter("\\
sets the scanner’s delimiter to “\\
");
“, which is a newline character. What this does is make the scanner take each line as an input element instead of whitespace (the default) as a delimiter. In this example, the sending and receiving of messages is separated by a line break between the server and the client.
Question 3: Why use PrintStream’s normal output System.out.println instead?
You can use
System.out.println
instead ofPrintStream
, they are both used to output content to the console. The use ofPrintStream
in the sample code is to send the message sent by the client to the server, and to print the message returned by the server to the console of the client.
Question 4: It is understandable that the server uses Scanner(socket.InputStream) to obtain client data, but why does the client also use Scanner(socket.InputStream) to obtain client data?
Both client and server use
Scanner(socket.getInputStream())
because they need to read data from the corresponding socket’s input stream. The client needs to read the message sent by the server, and the server needs to read the message sent by the client.
Question 5: Why is there a private static final BufferedReader KEYBOARD_INPUT = new BufferedReader(new InputStreamReader(System.in)); code, can’t it be directly replaced by Scanner (System.in)?
private static final BufferedReader KEYBOARD_INPUT = new BufferedReader(new InputStreamReader(System.in));
This code defines a static, read-only variable of typeBufferedReader
, throughSystem.in
associates the keyboard input stream with this variable. The purpose of this is to useKEYBOARD_INPUT.readLine()
on the client side to get the string entered by the user. SinceScanner(System.in)
uses a buffer to scan the input, it cannot meet the requirements of reading line by line, so you need to useBufferedReader
to accomplish.
3.BIO processing model (realize multi-user access to the same server)
Because in the previous model, only one user can interact with the server for a period of time, and once the user enters byebye, the server will be closed, but if I want multiple users to interact with the server, how can I achieve it? So the BIO processing model was introduced.
As can be seen from the structure shown in the figure, the solution is to create multiple Socket instances inside ServeSocket, and encapsulate each Socket instance in a thread to realize multi-thread communication. When a user connects, an independent communication thread is created. Each user can close its own thread independently
So you only need to modify the code on the server side
Service-Terminal:
package Example1907; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner; class EchoServer implements Runnable { // initialization Socket client = null; Scanner scanner = null; PrintStream out = null; boolean flag = true; // Incoming communication objects to create input and output streams and confirm client objects public EchoServer(Socket client){ try { this.client = client; this.scanner = new Scanner(client.getInputStream()); this.out = new PrintStream(client.getOutputStream()); }catch (Exception e){ e.printStackTrace(); } } // implement communication @Override public void run() { while (this.flag){ String value = scanner.nextLine().trim(); if (value. equalsIgnoreCase("byebye")){ this.flag = false; out.println("Bye Bye~"); } else { out.println("[server side]:" + value); } } // After the communication is completed, close all services try { scanner. close(); out. close(); client. close(); }catch (Exception e){ e.printStackTrace(); } } } //Service-Terminal public class javaDemo { public static void main(String[] args) throws Exception { ServerSocket server = new ServerSocket(9999); boolean flag = true; System.out.println("Waiting for client connection---------"); // Receive multiple clients through multiple threads while (flag){ Socket client = server. accept(); new Thread(new EchoServer(client)).start(); } } }
Client: still the same (here you can exercise yourself to rewrite the code)
package Example1908; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.Socket; import java.util.Scanner; //client public class javaDemo { private static final BufferedReader KEYBOARD_INPUT = new BufferedReader(new InputStreamReader(System.in)); public static String getString(String promp) throws Exception{ System.out.print(promp); String input = KEYBOARD_INPUT.readLine().trim(); return input; } public static void main(String[] args) throws Exception{ Socket client = new Socket("localhost",9999); Scanner scanner = new Scanner(client. getInputStream()); PrintStream out = new PrintStream(client. getOutputStream()); scanner.useDelimiter("\\ "); boolean flag = true; while (flag){ String msg = getString("[Client] Please enter the message you want to send").trim(); out. println(msg); if (scanner. hasNext()){ System.out.println(scanner.next().trim()); } if ("byebye".equalsIgnoreCase(msg)){ flag = false; } } scanner. close(); out. close(); client. close(); } }
Show results:
Service-Terminal:
The following javaDemo2 is user 1 and javaDemo4 is user 2
Client 1:
Client 2:
This model is BIO mode, but it can be found that there is no limit to the number of threads here, which means that once the number of users increases sharply, the performance will drop sharply, so it is necessary to add restrictions on threads, which is the real BIO (Blocking Io blocking Io mode)
4.UDP program
The difference between UDP transmission and Tcp is that it is oriented to connectionless and unreliable communication. If Tcp is to make a call, you must know the other party’s number to establish a connection before you can communicate. Then UDP is just shouting on the street. Some people You can hear what you have to say, and some people are too far away to hear you, but you don’t care.
This transmission method is often used in games. The so-called packet loss is caused by unreliable udp, but this transmission method is very fast and has low delay.
UDP commonly used classes are
Common methods of DatagramPackage:
Method name | Description |
---|---|
public DatagramPacket(byte[] buf , int length) | Construct a DatagramPacket object, use the specified byte array as data, and specify the length as the effective data length. |
public byte[] getData() | Get the data byte array in the DatagramPacket object. |
public int getLength() | Get the length of the data in the DatagramPacket object. |
Common methods of DatagramSocket:
Method Name | Description |
---|---|
DatagramSocket() | Creates an unbound datagram socket. |
DatagramSocket(int port) | Creates a datagram socket bound to the specified port. |
DatagramSocket(int port, InetAddress address) | Creates a datagram socket bound to the specified port and the specified local IP address. |
void send(DatagramPacket packet) | Send the specified data packet to the destination. |
void receive(DatagramPacket packet) | Receive a data packet and store it in the specified data packet object |
The following case implements a client sending a message to the server through udp and outputting the server return value
On the premise that the previous server is open:
package Example1910; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.nio.charset.StandardCharsets; public class javaDemo { public static void main(String[] args) throws Exception { // input data via keyboard System.out.println("Please enter the data you want to send"); BufferedReader input = new BufferedReader(new InputStreamReader(System.in)); String data = input. readLine(); // send packet DatagramSocket client = new DatagramSocket(9999); DatagramPacket packet = new DatagramPacket(data.getBytes(StandardCharsets.UTF_8),0,data.length(), InetAddress.getByName("localhost"),9999); client. send(packet); // receive packet byte redata[] = new byte[1024]; DatagramPacket repacket = new DatagramPacket(redata,0,redata.length); client.receive(repacket); System.out.println("The received data is" + new String(redata,0,redata.length,StandardCharsets.UTF_8)); client. close(); } }