java socket 进阶话题一: socket 客户端连接管理(一)

2014-11-24 03:00:24 · 作者: · 浏览: 5
(本文需有一定的tcp/ip 基础知识,并对java socket 以及java的多线程有一定的了解)

前段时间持续集成平台页面需展示每一个代理端执行控制台输出日志,为了减少主控端存储压力,代理端执行日志只存放在代理端所在主机,每次页面日志的获取直接从代理端获取。

主控和代理端的消息通讯使用java socket,网上关于java socket 基础 编程已经存在很多,本文主要探讨 java socket 中的一些延伸性的话题:多代理端同步消息通讯、
socket的分包和粘包,socket 客户端连接管理。

一、socket 客户端连接管理

持续集成的主控端必须要时刻监控代理端的状态,如果代理端没有连接需给出告警,而java socket的在不进行心跳控制的情况下无法真正的获取到代理端的状态

java socket 提供的方法 isConnected() 和 isClosed 无法真正的检测出客户端的状态,请看代码:

socket 服务端代码:

package com.test.socket.state;

import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
import java.util.concurrent.ConcurrentLinkedQueue;

import com.zsmart.core.common.DateHelper;


/**
 * socket 服务端
 * @author chm
 *
 */
public class ServerSocketTest {

    /**存放客户端连接集合*/
    public static ConcurrentLinkedQueue
  
    socketList = new ConcurrentLinkedQueue
   
    (); /** * 程序入口函数 * @param args */ public static void main(String[] args) { ServerSocketTest sst = new ServerSocketTest(); sst.startMonitor(); } /** * 监控客户端连接 */ public void startMonitor() { try { ServerSocket serverS = new ServerSocket(9912); Thread th = new Thread(new MonitorClientState()); th.start(); while (true) { Socket socket = serverS.accept(); socketList.add(socket); } } catch (Exception e) { e.printStackTrace(); } } /** * 客户端状态监控类 * @author chm * */ class MonitorClientState implements Runnable { public void run() { try { while(true){ Thread.sleep(2000); System.out.println("exec time: " + DateHelper.date2String(new Date())); for(Socket socketTemp : socketList){ System.out.println("ip: " + socketTemp.getInetAddress().getHostAddress() + " -- remote port: " + socketTemp.getPort() + " is close: " + socketTemp.isClosed() + " -- is connected: " + socketTemp.isConnected()); } } } catch (Exception e) { e.printStackTrace(); } } } }
   
  


socket 客户端代码:

package com.test.socket.state;

import java.net.Socket;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.zsmart.core.common.DateHelper;

/**
 * 客户端socket
 * @author chm
 *
 */
public class ClientSocket {

    public static void main(String[] args) {
        try {
            
            List
  
    listSocket = new ArrayList
   
    (); for(int i=0 ;i < 5 ;i++){ Socket socket = new Socket("localhost", 9912); listSocket.add(socket); } Thread.sleep(4000); Socket socket = listSocket.get(2); socket.close(); Socket socket1 = listSocket.get(3); socket1.close(); socket1 = null; System.out.println("Exec time: " + DateHelper.date2String(new Date()) + " 设置socket 连接为关闭状态"); } catch (Exception e) { e.printStackTrace(); } } }
   
  

我们在server端开始监听客户端的连接状态,每2秒打印出当前的连接状态,在客户端我们启动5个socket连接,过4 秒后直接关闭其中一个同时销毁一个,
并且我们的客户端在进行关闭操作后直接退出了,此时socket应用已经不存在了。看一下输出结果:


exec time: 2014-01-23 15:49:29
ip: 127.0.0.1 -- remote port: 64538 is close: false -- is connected: true
ip: 127.0.0.1 -- remote port: 64539 is close: false -- is connected: true
ip: 127.0.0.1 -- remote port: 64540 is close: false -- is connected: true
ip: 127.0.0.1 -- remote port: 64541 is close: false -- is connected: true
ip: 127.0.0.1 -- remote port: 64542 is close: false -- is connected: true


exec time: 2014-01-23 15:49:31
ip: 127.0.0.1 -- remote port: 64538 is close: false -- is connected: true
ip: 127.0.0.1 -- remote port: 64539 is close: false -- is connected: true
ip: 127.0.0.1 -- remote port: 64540 is close: false -- is connected: true
ip: 127.0.0.1 -- remote port: 64541 is close: false -- is connected: true
ip: 127.0.0.1 -- remote port: 64542 is close: false -- is connected: true


exec time: 2014-01-23 15:49:33
ip: 127.0.0.1 -- remote port: 64538 is close: false -- is connected: true
ip: 127.0.0.1 -- remote port: 64539 is close: false -- is connected: true
ip: 127.0.0.1 -- remote port: 64540 is close: false -- is connected: true
ip: 127.0.0.1 -- remote port: 64541 is close: false -- is connected: true
ip: 127.0.0.1 -- remote por