在上一小节中,分别实现了服务器端程序和客户端程序,当一个客户端程序请求服务器端时,服务器端就会结束阻塞状态,完成程序的运行。实际上,很多服务器程序都是允许被多个应用访问的,例如门户网站可以被多个用户同时访问,因此服务器都是多线程的。下面通过一个图例来表示多个用户访问同一个服务器,如下所示:
上图中代表的是多个客户端访问同一个服务器端,服务器端为每个客户端创建一对应的 Socket,并且开启一个新的线程使两个 Socket 建立专线进行通信。接下来根据上图所示的通信方式上一小节的程序进行改进,如下所示:
import java.io.OutputStream;import java.net.*;public class Server {public static void main(String[] args) throws Exception {//创建 TCPServer 对象,并调用 listen()方法new TCPServer().listen();}}//TCPServer 服务端class TCPServer{private static final int PORT = 7788; //定义一个端口号public void listen() throws Exception {//创建 ServerSocket 对象,监听指定的端口ServerSocket serverSocket = new ServerSocket(PORT);while (true) {//调用 ServerSocket 的 accept()方法与客户端建立连接final Socket client = serverSocket.accept();//开启一个新线程new Thread() {@Overridepublic void run() {super.run();//定义一个输出流对象OutputStream os;try {os = client.getOutputStream(); //获取客户端的输出流System.out.println("开始和客户端交互数据");os.write("我爱你".getBytes());Thread.sleep(5000); //使线程休眠 5000 毫秒System.out.println("结束和客户端交互数据");client.close();os.close();} catch (Exception e) {e.printStackTrace();}}}.start();}}}
上述代码块中使用多线程的方式创建了一个服务器端程序。通过在 while 循环中调用 accept()方法,不停的接收客户端发送的请求,当与客户端建立连接后,就会开启一个新的线程,该线程会去处理客户端发送的数据,而主线程仍继续等待状态。
为了验证服务器端程序时候实现了多线程,首先运行服务器端程序,之后运行三个客户端程序,当运行第一个客户端程序时,服务器马上就进行数据处理,打印出“开始于客户端交互数据”,在运行第 2 个和第 3 个客户端程序,会发现服务端也立刻做出回应,3 个客户端会话结束后分别打印各自的结束消息,如下图所示。这说明通过多线程的方式可以实现多个用户对同一个服务器的访问。
