Establish a stable multi-thread server using Java
content:
The structural port of the message system is the structure port monitoring thread class PortListenthread single client in the connection pool image class clientsingle packet forwarding type group primary server class Server summary about the author
There is also a Java area:
Teaching tools and product code and components all articles practical skills
Hou Guangmin (Wearebug@tang.com) July 2002
This article describes the process of establishing a multi-thread server using the Java language. The server uses an object to pass the message, using the queue mechanism in the thread, so that the performance of the server is greatly improved. This set of servers can be used in applications of various C / S or B / S structures.
The Java language is completely object-to-object, its thread mechanism and object serialization are particularly easy to use. Use Java to create a multi-thread server to easily be more convenient than other languages, if you use its exception handling mechanism to take advantage of it, Then you can build a business-grade multi-threaded server. Since the message queue and socket transmission are used, there is no problem with the message. This server can be used as a real-time chat server, multi-person collaborative collaborative servers, and more. The messaging system of the message system uses the server's message system that uses the mechanism of object transmission, not a string transmission that is often used. The benefits of using object transmission are convenient, if you need to create a new message, you only need to inherit from a unified base class, and then write your own implementation. This also complies with an important principle of object-oriented field: OCP (Open_Closed Princi), that is, a good design should be able to accommodate new features, but the increased mode is not modifying the original class, but add new classes. First create a base class: MSG, the sender and recipient of two domain Sender and Receiver separately record messages in this abstract class. These two domains are filled in when constructing a message class, and the Receiver domain can be empty, and the empty means that it can be sent to anyone, which is determined by the forwarding server. The method of this class includes obtaining the value of the two domains and the processing function of the message. The processing function process () is an empty function for the successor overload. After establishing this abstract base class, you can inherit it to complete your own class. For example, if I want to build a drawing system that collaborate work, but also supports the conversations between group members, then I can build the following set: SendtextMsg (String Sender, String Receiver, String Info) // To the specified People send dialogue.
AddLineMSG (String Sender, Point A, Point B) / / Draw a straight line between the specified point
AddRectangle (String Sender, Point Start, Point End) // Established a specified rectangle
Addrotundamsg (String Sender, Point Center, int RADIUS) // Established the specified circle
RemoveObjectmsg (String Sender, int ID) // Remove the specified number of graphics objects
......
Pushing in this class, there can be a lot of messages. In each class, it is handled by a method process () that handles the class, filling this method to implement the processing of the message class, and the server is only responsible for completing the forwarding function of the message. In this way, a set of messages is established. Server Structure If you want to server implementation for each client service, you should use multithreading, create a thread pool, and open up a thread in the pool when there is a client connection. Similarly, the message queue is to be used to avoid the loss of the loss of a large number of messages. This server is a hierarchical process. The relationship diagram is as follows:
The server's work process is like this, establishing a Server class as a primary class, which contains the portable function main (). In the constructor, an array is initialized to store the ClientSingle class, which is actually handled separately to connect the user. Then start a thread portListentHread, the role of the thread is to log in on the listener port, and it is handed over to the addclient () processing when someone is connected. Server's AddClient () method will create a ClientSingle object in that array and then hand it over to it. PortListenTenTenTenRead This thread class is in the start of the Run () function. First check if ServersCoket is empty, and do not have an error while the loop begins. Then enter a dead cycle listener: while (true) {// dead cycle monitor Try {socket clientsocket = null;
Clientsocket = serversocket.accept ();
Server.addclient (clientsocket); // Transfer Server processing
}
Catch (IOEXCEPTION E) {system.out.println ("error" E);} // Display error
}
After each client connected to the image class clientsingle in the connection pool, the server automatically creates an image of the client in the connection pool, all the operations are handed over to this image to perform, so the clientsingle must be To include some basic information about the client. For example, the name of the client, login time, etc. There are two message queues SendQueue (send queues) and ReceiveQueue messages in this class. The ClientSingle class is inherited from Thread, it is still a caller. Start the two subclinger class Singleaseender and SingleListener run when initialization. SINGLESENDER is responsible for monitoring instructions in the command send queue, is sent; SingLelistener is responsible for listening to no message arrival, and there is a message to the receiving queue and processed by ClientSingle. So the main task of ClientSingle is the processing of these two queues. These two queues can be implemented with a vector, very simple. // ------- Add the message to the send queue ------------
Synchronized Void Send (Object O)
{Sendqueue.Add (O);
}
In order to stabilize the operation of the control sub-thread, it is not encouraged to use TRUE in the Run () method, but use a Boolean variable Finish. External can stop the running of thread by setting this flag as a false. After the transmit sub-class class is started, the loop in Run () is executed (end flag in Finish), first determined whether the sending queue in the clientsingle is empty, and then re-judgments for the time when sleeping. While cycle. Do not initiate a message in the queue without the flight, and put it into the output stream. Public void run () {
While (! father.finish) {// loop listening
While (Father.V.Isempty ()) {// When the send queue is empty, thread sleep 500 milliseconds
Try {threeRead.sleep (500);
Catch (InterruptedException E) {system.out.println (e);
}
IF (! Father.v.isempty ()) {// The send queue is not empty
Try {
Object a = father.v.firstlement (); // Retrieve the first message in the queue
Father.v.removeEleMentat (0); // Remove OOS.WRITEOBJECT (a) from the queue; // Send the message
OOS.FLUSH ();
} catch (ioexception e) {
DisplayMessage ("Transmission Failed!");
Father.finish = false;
}
}
}
}
The receiving sub-threaded SingLELISTENER class and the sender thread are similar, and their Run () methods are almost. Different is that the receiving sub-thread adds the received message to the ClientSingle's receiving queue to process it. The RUN () method of the ClientSingle class is looped to the content in the receiving queue ReceiveQueue, waiting for an empty time; do not take out processing and forwarding in turn. The function of processing the message is ProcessMSG (), which is just executing the message class's Process () method. After processing, the method of the Server class is called for various types of forwarding. The packet forwarded implementation class Group GROUP has established a Group class in order to achieve a client group. In this class, there is a list of those that already exist in the connection pools to the CLIENTSINGLE class. As long as you traverse the entire list, you can access members in all groups. This list can be implemented with a Vector, or you can use a hash table, I recommend it, mainly to access it by name. The group object itself is also in the group list of the Server class. Packet functions are very important for multiplayer collaborative systems, especially when packets are operated on a shared space. Take the above collaborative drawing system as an example. If there are three people in 10 people who want to start with another stove, then they can't let others see it, this must have a "group" division. The primary server class Server Server class is the core class. It plays a global role in this framework. The classes described above are constructed and called. The domain of the Server class includes a set of groups to store the ClientSingle instance, which is the implementation of the connection pool. Also have a hash table to store the Group instance. The method of the Server class is the operation of these two classes. The purpose of establishing a clientsingle array is to ensure the stability of the server. In fact, you can also choose not to build it, just dynamically construct the object, but it is not easy to manage the connected users, and because the various operating systems have different processing, the dynamic establishment of the service thread will be unstable. So I first build an array as a container of these objects, which estimates the maximum number of connectors at the beginning. AddClient () function of the Server class: void addclient (socket socket) {
INT C = 0;
Try {while (SCH [C]! = NULL) C ;} // Search the empty space in the array
ArrayIndexOfboundsexception e) {
Try {socket.close ();} // Exception Close Tap Connection
Catch (IOEXCEPTION EE) {system.out.println ("Array Overflow");}
Return;
}
SCH [C] = New ClientSingle (C, Socket, Father, this); // Create a ClientSingle object in search position
}