Classic example of Java Socket network concurrent programming

Posted by mohson on Thu, 17 Feb 2022 23:56:57 +0100

The basic model of network programming is the client to server model, which simply means that two processes communicate with each other. For programmers, it will be much easier to master a programming interface and use a programming model. The Java SDK provides some relatively simple APIs to complete these tasks. Socket is one of them. For Java, these APIs exist with Java Net package, so as long as you import this package, you can prepare for network programming.

The basic model of network programming is the client to server model. In short, two processes communicate with each other, and then one of them must provide a fixed location, while the other only needs to know the fixed location. And establish the connection between the two, and then complete the data communication. The one that provides a fixed location is usually called the server, while the one that establishes the connection is usually called the client. Based on this simple model, you can enter the network programming.

There are many APIs that Java supports for this model. Here I just want to introduce the socket programming interface. For Java, the socket programming interface has been simplified. First, let's discuss how the service provider providing fixed location is established. Java provides ServerSocket to support it In fact, when you create a strength object of this class and provide a port resource, you establish a fixed location where other computers can access you, ServerSocket server=new ServerSocket(6789); A little note here is that the allocation of ports must be unique. Because the port is to uniquely identify the unique service of each computer, and the port number ranges from 0 to 65535, the first 1024 ports have been reserved by Tcp/Ip, so you can only allocate ports after 1024. Well, we have a fixed position All we need now is a connecting cable The connection line is first requested by the customer. Therefore, Java also provides a socket object to support it. As long as the client creates an instance object of socket to support it. Socket client

=new Socket(InetAddress.getLocalHost(),5678); The client must know the IP address of the server. For this, Java also provides a related class InetAddress. The instance of this object must be provided through its static method. Its static method mainly provides methods to obtain the local IP and obtain the InetAddress directly through the name or IP.

The above method can basically establish a connection for the two computers to communicate with each other, but how is the data transmitted? In fact, I/O operations are always closely related to network programming. Because the underlying network continues to process data, unless it is called remotely and the core of processing problems is execution, the data interaction still depends on IO operations, so you must also import java I need this bag java's IO operation is not complicated. It provides readers and writers for byte stream and Unicode, and then provides a buffer for data reading and writing.

BufferedReader in=new BufferedReader(new InputStreamReader(server.getInputStream()));

PrintWriter out=new PrintWriter(server.getOutputStream());

The above two sentences are to establish a buffer and change the original byte flow into Unicode for operation. The original byte flow comes from the two Socket methods, getInputStream() and getOutputStream(), which are used to obtain input and output respectively. Now that we have the basic model and basic operation tools, we can make a simple Socket routine

Service provider:

import java.io.*; 

import java.net.*; 

public class MyServer { 

public static void main(String[] args) throws IOException{ 

ServerSocket server=new ServerSocket(5678); 

Socket client=server.accept(); 

BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream())); 

PrintWriter out=new PrintWriter(client.getOutputStream()); 

while(true){ 

String str=in.readLine(); 

System.out.println(str); 

out.println("has receive."); 

out.flush(); 

if(str.equals("end")) 

break; 

} 

client.close(); 

} 

} 

The main purpose of this program is that the server continues to Receive the information written by the client. The client will exit the program after sending the "End" string, and the server will also respond with "Receive" to inform the client that the message has been received.

Client code:

import java.net.*; 

import java.io.*; 

 

public class Client{ 

static Socket server; 

 

public static void main(String[] args)throws Exception{ 

server=new Socket(InetAddress.getLocalHost(),5678); 

BufferedReader in=new BufferedReader(new InputStreamReader(server.getInputStream())); 

PrintWriter out=new PrintWriter(server.getOutputStream()); 

BufferedReader wt=new BufferedReader(new InputStreamReader(System.in)); 

 

while(true){ 

String str=wt.readLine(); 

out.println(str); 

out.flush(); 

if(str.equals("end")){ 

break; 

} 

System.out.println(in.readLine()); 

} 

server.close(); 

} 

} 

The client code is to accept the input of the client's keyboard, output the information, and then output "End" as an exit sign.

This program is just a simple communication between two computers. What if multiple clients access a server at the same time? You can try running another client and an exception will be thrown. So how to implement multiple clients?

In fact, a simple analysis shows that the Socket itself is the main communication channel between the customer and the service, and the server agrees to establish communication with the customer through the accept method In this way, when the customer establishes the Socket. The server will also use this connection to communicate successively. In that case, as long as we have multiple connections. Then our program can be changed as follows:

The server:

import java.io.*; 

import java.net.*; 

 

public class MyServer { 

public static void main(String[] args) throws IOException{ 

ServerSocket server=new ServerSocket(5678); 

while(true){ 

Socket client=server.accept(); 

BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream())); 

PrintWriter out=new PrintWriter(client.getOutputStream()); 

while(true){ 

String str=in.readLine(); 

System.out.println(str); 

out.println("has receive."); 

out.flush(); 

if(str.equals("end")) 

break; 

} 

client.close(); 

} 

} 

} 

Only an outer While loop is added here. The purpose of this loop is to allocate a Socket for a client when it comes in until the client completes an interaction with the server, which is to receive the client's "End" message So now the interaction between multiple customers is realized. But The problem comes again. Although this has solved many customers, it is implemented in line. That is to say, when a client and the server complete a communication, the next client can come in and interact with the server. It is impossible to serve at the same time, so how can we communicate with each other and at the same time? Obviously, this is a problem of parallel execution. So threading is the best solution.

So the following question is how to use threads The first thing to do is to create a Thread and make it connected to the network connection. Then the Thread performs the operation just now. To create a Thread, either directly inherit the Thread or implement the Runnable interface. To establish a connection with the Socket, just pass the reference To execute the Thread, we must rewrite the run method, and what the run method does is what the single threaded version of main did just now. Therefore, our program becomes like this:

import java.net.*; 

import java.io.*; 

 

public class MultiUser extends Thread{ 

private Socket client; 

 

public MultiUser(Socket c){ 

this.client=c; 

} 

 

public void run(){ 

try{ 

BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream())); 

PrintWriter out=new PrintWriter(client.getOutputStream()); 

//Mutil User but can't parallel 

while(true){ 

String str=in.readLine(); 

System.out.println(str); 

out.println("has receive."); 

out.flush(); 

if(str.equals("end")) 

break; 

} 

client.close(); 

}catch(IOException ex){ 

}finally{ 

} 

} 

 

public static void main(String[] args)throws IOException{ 

ServerSocket server=new ServerSocket(5678); 

while(true){ 

//transfer location change Single User or Multi User 

MultiUser mu=new MultiUser(server.accept()); 

mu.start(); 

} 

} 

} 

My class inherits directly from the Thread class And through the constructor to pass the reference and establish a relationship with the customer Socket, so that each Thread has a. A communication channel Similarly, we can fill in the run method and hand over the previous operations to the Thread to complete, so that a multi client parallel Socket can be established.