一个简单网络服务器类的实现

网络服务器,顾名思义是一个可以接受连接的host,我们要实现的网络服务器类是一个

1.能够实现多个连接

2.仅仅通过继承或实现网络服务器类(或接口)的处理就能实现不同的连接功能

3.当服务器关闭时,已有建立的私有连接不被中断,但服务器不在接受新的连接

针对以上功能我们分解一下要实现的模块:

1.多线程实现多个连接,当serverSocket accept到一个连接请求时,开启一个独立的线程

2.关闭server后不接受连接,为关闭serverSocket的accept所阻塞的线程,关闭有两种方式,一种是中断,一种是close serverSocket。

下面不是最后的成品,但我认为尝试过程也会带给人很多启示,所以请跟我一起进行尝试吧。

我们首先想到的方式应该是这样的:

TCPServer类:

 1 public class TCPServer extends Thread {
 2 
 3     ServerSocket server = null;
 4     volatile boolean shouldstop = false;
 5 
 6     public synchronized void startServer(int port) throws Exception {
 7         server = new ServerSocket(port);
 8         new TCPServer().start();
 9     }
10 
11     public void run() {
12         while (!shouldstop) {
13             try {
14                 Socket dataSocket = server.accept();
15                 TCPConnection newConnection = new TCPConnection(dataSocket);
16                 newConnection.start();
17             } catch (IOException e) {
18                 e.printStackTrace();
19             }
20         }
21     }
22     
23     public synchronized void stopServer(){
24         if(server!=null){
25             shouldstop = true;
26             interrupt();
27             try {
28                 server.close();
29             } catch (Exception e) {
30             }
31             server = null;
32         }
33     }
34 }

TCPConnection类:

 1 import java.net.Socket;
 2 
 3 
 4 public class TCPConnection extends Thread{
 5 
    
    Socket dataSocket;
6 public TCPConnection(Socket dataSocket) { 7 this.dataSocket = dataScoket; 8 } 9 10 public void run(){ 11 // dosomething(); 12 } 13 }

TCPServer类在run方法中循环等待接受请求连接,当有请求连接到来时,就为这个私有连接新建一个TCPConnection线程,并启动它。

看上去上面的实现还是可以的,每个连接都能独立运行,而且stopServer方法也做到了关闭server后并影响私有连接的通讯。但是要求二“仅通过继承或实现 TCPServer就能做到对连接功能的修改”

为了完成以上要求,显然要把TCPConnection集成到TCPServer中去。那么如何集成才能做到通过继承或实现 TCPServer 就能做到对连接的修改呢。

这里我采用的方式是让私有连接和TCPServer共享run方法,然后利用标志位来实现私有连接处理自己的事情,服务器Socket循环等待连接。

 1 package com.choi.net.server;
 2 
 3 import java.io.IOException;
 4 import java.net.ServerSocket;
 5 import java.net.Socket;
 6 
 7 /**
 8  * @author Choi
 9  * 
10  * @version 1.0
11  * 
12  * */
13 
14 public class TCPServer implements Cloneable, Runnable {
15 
16     Thread runner = null;
17     protected ServerSocket server = null;
18     Socket data = null;
19     volatile boolean shouldStop = false;
20 
21     public synchronized void startServer(int port) throws IOException {
22         if (runner == null) {
23             server = new ServerSocket(port);
24             runner = new Thread(this);
25             runner.start();
26         }
27     }
28 
29     public synchronized void stopServer() {
30         if (server != null) {
31             shouldStop = true;
32             runner.interrupt();
33             runner = null;
34             try {
35                 server.close();
36             } catch (Exception e) {
37             }
38             server = null;
39         }
40     }
41 
42     @Override
43     public void run() {
44         if (server != null) {
45             while (!shouldStop) {
46                 try {
47                     Socket dataSocket = server.accept();
48                     System.out.println("建立一个连接");
49                     TCPServer newServer = (TCPServer) clone();
50                     newServer.server = null;
51                     newServer.data = dataSocket;
52                     newServer.runner = new Thread(newServer);
53                     newServer.runner.start();
54                 } catch (Exception e) {
55                 }
56             }
57         } else {
58             System.out.println("新连接可用");
59             run(data);
60         }
61     }
62 
63     public void run(Socket dataSocket) {
64         System.out.println("空处理");
65     }
66 }

通过让TCPServer实现cloneable接口的方式来建立新的连接,这样做只是为了方便;当我们为私有连接创建完新线程后把新对象的server赋值为null,这样run方法中的if(server!=null)就能把服务器Socket和私有连接Socket的处理分开了。私有连接的处理是63~65的空方法。

如果想要实现特有功能,只需要继承TCPServer并在子类中从写run(Socket dataSocket)就可以了。

完整的代码和实例,可在我的github主页下载:https://github.com/choitony/TCPServer

原文地址:https://www.cnblogs.com/chaiwentao/p/4678277.html