This is the fifth day of my participation in the November Gwen Challenge. Check out the details: The last Gwen Challenge 2021
ServerSocket (juejin. Cn) : Juejin. ServerSocket (juejin. Cn) : Juejin.
Request queue length
When the server process is running, it may be listening for connection requests from multiple clients at the same time. For example, whenever a client process executes the following code:
Socket socket = new Socket("123.345.746.2", 80);
Copy the code
This means that a customer connection request is being listened on port 80 of the remote 123.345.746.2 host. The task of managing customer connection requests is handled by the operating system, which stores them in a first-in, first-out queue. Many operating systems limit the maximum length of a queue, typically 50. When the number of connection requests in the queue reaches the maximum capacity of the queue, the host of the server process rejects new connection requests. The queue can continue to add new connection requests only when the server process removes connection requests from the queue via the ServerSocket accept() method, leaving the queue empty.
For the client process, if its connection request is queued to the server, it means that the connection between the client and the server has been established and the client process returns normally from the Socket constructor. The Socket constructor throws a ConnectionException if the connection request from the client process is rejected by the server.
The Backlog parameter of the ServerSocket constructor is used to explicitly set the length of the connection request queue, which overrides the maximum length of the queue defined by the operating system. It is important to note that if the backlog value is set to 0 or greater than the maximum size of the os-qualified queue or is absent, the backlog will still take the os-qualified queue maximum size.
Accept and close connections to clients
The Accept () method of the ServerSocket fetches a client’s connection request from the connection request queue and creates a Socket object that connects to the client. The server then gets input and output streams from the Socket object and can exchange data with the client. However, if the client is disconnected while the server is sending data, the server will throw a SocketException subclass of IOException and the server will exit the program, so we need to catch this exception so that the server can continue to communicate with other clients.
You can put code that communicates with a single client into a try block, and if an exception is encountered, the exception is caught by the catch block. The try block should be followed by a finally block that closes the Socket and disconnects from the client.
public void server(a)
{
while(true)
{
Socket socket = null;
try {
socket = serverSocket.accept();// Wait for the client to connect
System.out.println("Client connected, address:"+socket.getInetAddress()+"Port number:"+socket.getPort());
PrintWriter writer = this.getWriter(socket);
BufferedReader reader = this.getReader(socket);
String msg = null;
while((msg = reader.readLine())! =null)
{
System.out.println(socket.getInetAddress()+""+socket.getPort()+"Message sent:"+msg);
writer.println("Server received:"+ msg); }}catch (IOException e) {
// You can choose to print exceptions or not
//e.printStackTrace();
}finally {
try {
if(socket! =null)
socket.close();
} catch(IOException e) { e.printStackTrace(); }}}}Copy the code
Multithreaded server
When a Server receives a customer connection, it communicates with the customer, disconnects from the customer, and then receives the next customer connection. But if more than one customer requests a connection at the same time, those customers must queue up for a response.
Many practical applications require servers capable of serving multiple customers simultaneously. The HTTP server is the most obvious example. At any given moment, the HTTP server may receive a large number of customer requests, and each customer expects a quick response from the HTTP server. If you keep customers waiting for a long time, your website will lose credibility and reduce traffic. Therefore, a multithreaded approach can be used to enable the server to accept multiple user requests simultaneously.
When the accept() function is no longer blocked, it indicates that a client is connected to the server. Then create a new thread and pass the socket to the thread for operation. The code is as follows:
public class ServerDemo {
private int port = 40000;
private ServerSocket serverSocket;
class ThreadServer extends Thread {
Socket socket;
public PrintWriter getWriter(Socket socket) throws IOException {
OutputStream socketoutput = socket.getOutputStream();
PrintWriter printWriter = new PrintWriter(socketoutput, true);
return printWriter;
}
public BufferedReader getReader(Socket socket) throws IOException {
InputStream socketinput = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socketinput));
return bufferedReader;
}
public ThreadServer(Socket s) {
this.socket = s;
}
@Override
public void run(a) {
System.out.println("Client connected, address:" + socket.getInetAddress() + "Port number:" + socket.getPort());
try {
PrintWriter writer = this.getWriter(socket);
BufferedReader reader = this.getReader(socket);
String msg = null;
msg = reader.readLine();
while((msg) ! =null) {
System.out.println(socket.getInetAddress() + "" + socket.getPort() + "Message sent:" + msg);
writer.println("Server received:"+ msg); msg = reader.readLine(); }}catch (IOException e) {
} finally {
try {
if(socket ! =null)
socket.close();
} catch(IOException e) { e.printStackTrace(); }}}}public ServerDemo(a) throws IOException {
serverSocket = new ServerSocket(port);
System.out.println("Server started");
}
public void server(a)
{
while(true)
{
Socket socket = null;
try {
socket = serverSocket.accept();// Wait for the client to connect
ThreadServer threadServer = new ThreadServer(socket);
threadServer.start();
} catch (IOException e) {
System.out.println("Client :"+socket.getInetAddress()+"Disconnected, server continues to run");
}finally{}}}public static void main(String[] args) throws IOException {
newServerDemo().server(); }}Copy the code
The client code does not need to be changed, but there is a big hole to be aware of: When the socket is set to multithreaded mode, the finally block cannot continue to be written in the main thread. Otherwise, when a new thread is created, the main thread will continue to execute the code until the socket is closed. This allows multiple clients to access the server at the same time, with the following effect:
Disabling the server Socket
The close() method of the ServerSocket causes the server to release occupied ports and disconnect from all clients. When a server program finishes running, the operating system releases the port occupied by the server, even if ServerSocket’s close() method is not executed. Therefore, the server program does not have to execute ServerSocket’s close() method before terminating.
In some cases, you can explicitly call the ServerSocket close() method if you want to release a server port in time so that other programs can occupy it.
Obtain ServerSocket information
The following two functions are provided by ServerSocket to get the server bound IP address and the bound port number:
public InetAddress getInetAddress()
public int getLocalPort()
Copy the code
Most servers listen on a fixed port so that clients can access the server. However, anonymous ports are generally used for temporary communication between the server and the client. When the communication ends, the connection is disconnected and the temporary port occupied by the ServerSocket is released.