The
Jabberserver can work correctly, but only one client service at a time. In a typical server, we want to be able to handle requests from multiple customers at the same time. The key to solve this problem is the multithreading mechanism. For those languages that do not support multithreading in their own right, it is extremely difficult to achieve this requirement. Through the 14th chapter of the study, we already know that Java has to multithreading processing to simplify as much as possible. Because Java threading is straightforward, it's not difficult to let servers control more than one customer. The most basic method of
is to create a single serversocket in the server (program) and call accept () to wait for a new connection. Once accept () returns, we get the socket for the result and use it to create a new thread to serve only that particular customer. Then call accept () and wait for the next new connection request.
for the following server code, you can see that it is very similar to the Jabberserver.java example, except that all operations that serve a particular customer have been moved into a separate thread class:
: Multijabberserver.java//A server that uses multithreading to handle/any number of clients.
Import java.io.*;
Import java.net.*;
Class Serveonejabber extends Thread {private socket socket;
Private BufferedReader in;
Private PrintWriter out;
Public Serveonejabber (socket s) throws IOException {socket = s;
in = new BufferedReader (New InputStreamReader (Socket.getinputstream ()));
Enable auto-flush:out = new PrintWriter (New BufferedWriter new OutputStreamWriter (
Socket.getoutputstream ()), true); If any of the above calls throw A//exception, the caller is responsible for//closing the socket.
Otherwise the thread//would close it. Start ();
Calls run ()} public void Run () {try {while (true) {String str = in.readline ();
if (Str.equals ("End")) a break;
System.out.println ("Echoing:" + str); OUT.PRINTLN (STR);
} System.out.println ("Closing ...");
catch (IOException e) {} finally {try {socket.close ();
The catch (IOException e) {}}} is public class Multijabberserver {static final int PORT = 8080;
public static void Main (string[] args) throws IOException {ServerSocket s = new ServerSocket (PORT);
System.out.println ("Server started");
try {while (true) {//Blocks until a connection occurs:socket Socket = S.accept ();
try {new Serveonejabber (socket);
catch (IOException e) {//If it fails, close the socket,//otherwise the thread would close it:
Socket.close ();
}}} finally {S.close (); }
}
} ///:~
Each time a new customer requests a connection, the serveonejabber thread gets the socket object generated by accept () in main (). Then as always, it creates a bufferedreader and automatically refreshes the PrintWriter object with the socket. Finally, it calls the Special method start () of thread to initialize the thread, and then call Run (). The action taken here is the same as the precedent: read something from the lasso and then feed it back until a special "end" flag is encountered.
Similarly, the removal of sockets must be carefully designed. In this case, the socket is created outside the Serveonejabber, so cleanup can be "shared." If the Serveonejabber builder fails, you can simply "throw" a violation to the caller and the caller will be responsible for the purge of the thread. But if the builder succeeds, the Serveonejabber object must be responsible for the purge of the thread, which is done in its run ().
Note how simple Multijabberserver is. As before, we created a serversocket and called accept () to allow the establishment of a new connection. But this time, the return value of accept (a socket) is passed to the builder for Serveonejabber, which creates a new thread and controls that connection. When a connection is interrupted, the thread can simply disappear.
If the ServerSocket creation fails, the violation is thrown again through main (). If successful, the try-finally code block at the outer layer can guarantee correct cleanup. The Try-catch block in the inner layer is responsible only for preventing the Serveonejabber builder from failing, and if the builder succeeds, the Serveonejabber thread will turn off the corresponding socket.
to verify that server code does serve multiple customers, the following program creates many customers (using threads) and establishes a connection to the same server. The "presence time" of each thread is limited. Once it expires, leave room to create a new thread. The maximum number of threads allowed to be created is determined by the final int maxthreads. You will notice that this value is critical, because if you set it very large, the thread might run out of resources and produce unpredictable program errors.
: Multijabberclient.java//Client that tests the Multijabberserver//by starting up multiple clients.
Import java.net.*;
Import java.io.*;
Class Jabberclientthread extends Thread {private socket socket;
Private BufferedReader in;
Private PrintWriter out;
private static int counter = 0;
private int id = counter++;
private static int threadcount = 0;
public static int ThreadCount () {return threadcount;
Public Jabberclientthread (inetaddress addr) {System.out.println ("making client" + ID);
threadcount++;
try {socket = new socket (addr, multijabberserver.port);
The catch (IOException e) {//If the creation of the socket fails,//Nothing needs to is cleaned up. The try {in = new BufferedReader InputStreamReader (socket.getinputstream
())); Enable auto-flush:out = new PrintWriter (new BufferedWriter (New OUTPUTSTREAMWRiter (Socket.getoutputstream ()), true);
Start (); catch (IOException e) {//The socket should be closed to any//failures other than the socket/CO
Nstructor:try {socket.close ();
The catch (IOException E2) {}}//otherwise the socket would be closed by//the run () of the thread.
public void Run () {try {= 0; I < i++) {out.println ("Client" + ID + ":" + i);
String str = in.readline ();
System.out.println (str);
} out.println ("End");
The catch (IOException e) {} finally {//Always close It:try {socket.close (); catch (IOException e) {} threadcount--;
Ending this thread}} The public class Multijabberclient {static final int max_threads = 40; public static void Main (string[] args) throws IOException, interruptedexception {inetaddress addr = Ine Taddress.getbynamE (null);
while (true) {if (Jabberclientthread.threadcount () < max_threads) New Jabberclientthread (addr);
Thread.CurrentThread (). Sleep (100); }
}
} ///:~
The Jabberclientthread builder gets a inetaddress and uses it to open a socket. You may have seen a pattern where the socket is definitely used to create some kind of reader and/or writer (or InputStream and/or OutputStream) object, which is the only way to use a socket (of course, we can consider writing a Two classes to automate these operations and avoid a lot of repetitive code writing work. Similarly, start () performs the initialization of the thread and invokes run (). Here, messages are sent to the server, and information from the server is displayed on the screen. However, the thread's "presence time" is limited and will eventually end. Note When the socket is created, but before the builder completes, if the builder fails, the socket is purged. Otherwise, the responsibility to call Close () for the socket falls to the head of the Run () method.
The ThreadCount Trace calculates the number of Jabberclientthread objects currently in existence. It will add value as part of the builder and decrement when run () exits (the run () exit means the thread aborts). In Multijabberclient.main (), you can see that the number of threads is checked. If the number is too large, the excess is temporarily not created. The method then enters the hibernate state. As a result, once some of the threads are finally aborted, the more threads can be created. You can experiment with increasing max_threads to see how many threads (connections) You can use to make your system resources less dangerous.