现实中的socket可能会因为各种原因done机,但这么重要的服务器怎么能允许这种事情发生?这次我们就来通过一个线程去监控socket服务器,如果done机重新将其启动。
下面是监控项目和socket服务器项目的目录结构:
因为线程是每两秒发送一次请求检测服务器是否done机,类似心跳,所以包名起作heart。
来看客户端heart代码:
Entity 实体类:用来构建测试请求的数据结构
package heart; import java.io.Serializable; public class Entity implements Serializable { private static final long serialVersionUID = 1L; private String name; private String sex; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } @Override public String toString() { return "Entity [name=" + name + ", sex=" + sex + "]"; } }
客户端同步线程代码:
package heart; public class ClientHeart extends Thread { @Override public void run() { try { while (true) { ClientSender.getInstance().send(); synchronized (ClientHeart.class) { // this.wait(5000); Thread.sleep(2000); } } } catch (Exception e) { e.printStackTrace(); } } /** * 程序的入口main方法 * * @param args */ public static void main(String[] args) { ClientHeart client = new ClientHeart(); client.start(); } }
客户端发送消息代码:
package heart; import java.io.ObjectOutputStream; import java.net.InetAddress; import java.net.Socket; import echoserver.EchoServer; import heart.Entity; public class ClientSender { private ClientSender() { } Socket sender = null; private static ClientSender instance; public static ClientSender getInstance() { if (instance == null) { synchronized (ClientHeart.class) { instance = new ClientSender(); } } return instance; } @SuppressWarnings("static-access") public void send() { try { sender = new Socket("192.168.1.166", 9090); while (true) { ObjectOutputStream out = new ObjectOutputStream(sender.getOutputStream()); Entity obj = new Entity(); obj.setName("xiaoming"); obj.setSex("男"); out.writeObject(obj); out.flush(); System.out.println("已发送..."); Thread.sleep(5000); } } catch (Exception e) { EchoServer myServer = new EchoServer(); System.out.println("连接异常"); try { myServer.main(null); } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } }
发送消息代码中,可以看到socket是重新起的一个socket,和socket服务器并无关联,与服务器中的heart代码中的服务器相对应(如果加上监控socket的服务器,服务器项目中其实是有两个服务器的,一个作为socket服务器,一个作为监控socket的服务器),这样就可以避免一直重新new出socket造成的channel异常。
一开始我选择用过quartz定时器作为轮巡监测,也试着搭建过webservice,但是都失败了。quartz轮巡会造成socket服务器的阻塞,webservice的话,如果服务器done机,那么这个webservice也就跟着一起done掉了,更不要谈什么监测了,所以,创建一个单线程的监测,速度又快(2秒一次完全够了),又安全,何乐不为?
注意,客户端的config包中的xml配置文件其实是和服务器中的一模一样的,我是在监测服务器的项目中为了能够在服务器done机后重新启动服务器,在buildPath中加入了服务器的项目,但是服务器项目中需要引用EchoServer.xml这个文件,所以在客户端重新复制了一份。
以下是服务器端的监测线程:
package heart; import java.io.ObjectInput; import java.io.ObjectInputStream; import java.net.ServerSocket; import java.net.Socket; import heart.Entity; public class ServerHeart extends Thread { private ServerSocket server = null; Object obj = new Object(); @Override public void run() { try { server = new ServerSocket(9090); while (true) { Socket client = server.accept(); synchronized (obj) { new Thread(new Client(client)).start(); } } } catch (Exception e) { e.printStackTrace(); } } /** * 客户端线程 * * @author USER * */ class Client implements Runnable { Socket client; public Client(Socket client) { this.client = client; } @Override public void run() { try { while (true) { ObjectInput in = new ObjectInputStream(client.getInputStream()); Entity entity = (Entity) in.readObject(); System.out.println(entity); } } catch (Exception e) { e.printStackTrace(); } } } /** * 程序的入口main方法 * * @param args */ public static void main(String[] args) { System.out.println("开始检测服务器是否done机..."); new ServerHeart().start(); } }
下面附上两个项目的传送门:http://files.cnblogs.com/files/fengwenzhee/monitorSocket.rar
另外:SSsocket(服务器项目)中有一个Test.jar文件,这个可不是jar包,里面是socket服务器的测试原件,直接解压就可以用了。
如果要在linux系统测试,就把两个项目打成可执行的jar(runnable JAR file),然后导入linux虚拟机中(我是通过putty这个辅助软件导入的)地址:http://files.cnblogs.com/files/fengwenzhee/putty.rar,命令在我另一篇博客中有提到,然后jar -jar monitor.jar命令启动项目,(我是直接启动的监控项目,正好测试一下是否成功拉起done机的socket服务器)。
测试成功,至于服务器的socket我用的是quicksocket,关于服务器有什么不明白的可以直接留言。
转载请注明出处。