上篇文章介绍了Socket和ServerSocket简单使用和源码,服务器端会对每个客户端请求创建一个线程,为使服务器端能同时处理多个客户端请求,可以采用多线程的方式。本文仅对实例进行简单记录,如下。
服务器端
import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class MultiJabberServer { static final int PORT = 8080; public static void main(String[] args) throws IOException{ ServerSocket serverSocket = new ServerSocket(PORT); System.out.println("Server Started"); try { while(true) { Socket socket = serverSocket.accept(); try { new ServeOneJabber(socket); } catch (IOException e) { // If it fails, close the socket, // otherwise the thread will close it: socket.close(); } } } finally { serverSocket.close(); } } }
while循环获取连接,并构造ServerOneJabber,启动线程处理客户端交互。
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.Socket; public class ServeOneJabber extends Thread{ private Socket socket; private BufferedReader in; private PrintWriter out; public ServeOneJabber(Socket socket) throws IOException{ this.socket = socket; in = new BufferedReader(new InputStreamReader(socket.getInputStream())); out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true); start(); } public void run() { try { while (true) { String str = in.readLine(); if ("END".equals(str)) { break; } System.out.println("Echoing: " + str); out.println("Got: " + str); } System.out.println(socket + ", seesion closing...."); } catch (IOException e) { System.out.println(e.getMessage()); } finally { try { socket.close(); } catch (Exception e2) { System.out.println("Socket not closed"); } } } }
原理与上篇文章一样,获取输入输出流,对请求信息进行处理和响应。
客户端
import java.io.IOException; import java.net.InetAddress; public class MultiJabberClient { static final int MAX_THREADS = 40; public static void main(String[] args) throws IOException, InterruptedException{ InetAddress addr = InetAddress.getByName(null); for(int i = 0; i < MAX_THREADS; i++) { new JabberClientThread(addr); Thread.sleep(100); } // while(true) { // if(JabberClientThread.threadCount() < MAX_THREADS) { // new JabberClientThread(addr); // } // Thread.sleep(100); // } } }
构造线程JabberClientThread,构建Socket,与服务器端连接。
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.InetAddress; import java.net.Socket; public 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); } catch (IOException e) { // If the creation of the socket fails, // nothing needs to be cleaned up. System.out.println("Socket failed"); return; } try { in = new BufferedReader(new InputStreamReader(socket.getInputStream())); out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true); start(); } catch (IOException e) { // The socket should be closed on any // failures other than the socket // constructor: try { socket.close(); } catch (IOException e2) { System.err.println("Socket not closed"); } } } public void run() { try { for(int i = 0; i < 5; i++) { out.println("Client " + id + ":" + i); String str = in.readLine(); System.out.println(str); } out.println("END"); } catch (IOException e) { System.err.println("IO Exception"); } finally { try { socket.close(); } catch (IOException e2) { System.err.println("Socket not closed"); } threadCount--; } } }
其中包含成员属性id和threadCount,每创建一个线程,id递增(采用类成员控制);threadCount作为线程数量的记录,线程创建时加一,结束时减一。
运行结果如下:
服务器端:
Server Started Echoing: Client 0:0 Echoing: Client 0:1 Echoing: Client 0:2 Echoing: Client 0:3 Echoing: Client 0:4 Socket[addr=/127.0.0.1,port=42998,localport=8080], seesion closing.... Echoing: Client 1:0 Echoing: Client 1:1 Echoing: Client 1:2 Echoing: Client 1:3 Echoing: Client 1:4 Socket[addr=/127.0.0.1,port=43000,localport=8080], seesion closing.... ...... Echoing: Client 39:0 Echoing: Client 39:1 Echoing: Client 39:2 Echoing: Client 39:3 Echoing: Client 39:4 Socket[addr=/127.0.0.1,port=43076,localport=8080], seesion closing....
客户端:
Making client 0 Got: Client 0:0 Got: Client 0:1 Got: Client 0:2 Got: Client 0:3 Got: Client 0:4 Making client 1 Got: Client 1:0 Got: Client 1:1 Got: Client 1:2 Got: Client 1:3 Got: Client 1:4 ..... Making client 39 Got: Client 39:0 Got: Client 39:1 Got: Client 39:2 Got: Client 39:3 Got: Client 39:4