现实中的 socket 可能会因为各种原因 done 机,但这么重要的服务器怎么能允许这种事情发生?这次我们就来通过一个线程去监控 socket 服务器,如果 done 机重新将其启动。
下面是监控项目和 socket 服务器项目的目录结构:
因为线程是每两秒发送一次请求检测服务器是否 done 机,类似心跳,所以包名起作 heart。
来看客户端 heart 代码:
Entity 实体类:用来构建测试请求的数据结构
- package heart;
- import java.io.Serializable;
- public classEntityimplements Serializable {
- private static final longserialVersionUID = 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 classClientHeartextends 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 =newSocket("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 classServerHeartextends Thread {
- privateServerSocket server =null;
- Object obj =new Object();
- @Override
- public void run() {
- try {
- server =newServerSocket(9090);
- while(true) {
- Socket client = server.accept();
- synchronized (obj) {
- newThread(new Client(client)).start();
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- /**
- * 客户端线程
- *
- * @author USER
- *
- */
- classClientimplements 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,关于服务器有什么不明白的可以直接留言。
来源: http://www.cnblogs.com/fengwenzhee/p/7119546.html