一个项目看java TCP/IP Socket编程(1.3版)

前一段时间刚做了个java 程序和网络上多台机器的c程序通讯的项目,遵循的是TCP/IP 协议,用到了java 的Socket编程。网络通讯是java 的强项,用TCP/IP 协议可以方便的和网络上的其他程序互通消息。

先来介绍下网络协议:
    TCP/IP
        Transmission Control Protocol 传输控制协议
        Internet Protocol 互联网协议
    UDP
        User Datagram Protocol 用户数据协议

连接协议:
    分为:
    面向连接协议: Connection Oriented Protocol
    非连接协议: Connectionless Protocol

    1).面向连接协议是指两台电脑在传输数据前,先会建立一个专属的连接。就如电信局的交换机会为打电话双方提供专属连接一样。
    Internet上的面向连接协议就是TCP/IP
    特点:确认回应;分组序号;流量控制。
    TCP/IP 属于可靠性传输,适合不容许有传输错误的网络程序设计使用

    2).非连接协议:无专属连接,无分组,容错,距离短,可同时对多台电脑进行数据传输
    Internet上的非连接协议就是UDP

    TCP在网络通信上有极强的生命力,例如远程连接(Telnet)和文件传输(FTP)都需要不定长度的数据被可靠地传输。相比之下UDP操作简单,而且仅需要较少的监护,因此通常用于局域网高可靠性的分散系统中client/server应用程序。


Socket 是程序与网络间的一种接口,大部分网络应用程序都是点对点的,所谓点就是服务器端和客户端所执行的程序。Socket是用来接收和传送分组的一个端点。

java 的Socket编程要用到java .net 包,最常用的是net包下的6个类:InetAddress(互联网协议 (IP) 地址)类,Socket(套接字)类,ServerSocket(套接字服务器)类,DatagramSocket(发送和接收数据报包的套接字) 类,DatagramPacket(数据报包)类,MulticastSocket(多播数据报套接字类用于发送和接收 IP 多播包)类,其中InetAddress、Socket、ServerSocket类是属于TCP面向连接协议,DatagramSocket、 DatagramPacket和MulticastSocket类则属于UDP非连接协议的传送类。

本项目因为使用TCP/IP 协议,主要用到Socket和ServerSocket类

项目代码如下

Java 代码
  1. package  com.sse.monitor.serv;  
  2.   
  3. import  java .io.DataInputStream;  
  4. import  java .io.IOException;  
  5. import  java .io.InputStream;  
  6. import  java .io.OutputStream;  
  7. import  java .io.BufferedOutputStream;  
  8.   
  9. import  java .net.Socket;  
  10. import  java .net.UnknownHostException;  
  11. import  java .util.ArrayList;  
  12.   
  13. import  com.sse.monitor.bean.Message;  
  14. import  com.sse.monitor.bean.MessageHead;  
  15. import  com.sse.monitor.bean.ResponseMessage;  
  16. import  com.sse.monitor.form.ListenerInvoke;  
  17. import  com.sse.monitor.form.MainForm;  
  18. import  com.sse.monitor.util.SwingUtils;  
  19.   
  20. /**  
  21.  * Socket套接字工厂,对外接口是静态方法 SocketFactory.request(String, String, String, int)   
  22.  * Copyright: Copyright (c) 2008   
  23.  * Company: conserv  
  24.  * @author cuishen  
  25.  * @version 1.3  
  26.  */   
  27. public   class  SocketFactory {  
  28.     private  Socket socket =  null ;  
  29.     private  String targetIpAddress =  null ;  
  30.     private   int  targetPort =  0 ;  
  31.     private   static  SocketFactory sf =  new  SocketFactory();  
  32.   
  33.     public  SocketFactory() {  
  34.     }  
  35.   
  36.     /**  
  37.      * 建立一条TCP/IP 连接  
  38.      * @param targetIpAddress String 目标ip地址  
  39.      * @param targetPort String 目标端口  
  40.      * @throws IOException  
  41.      */   
  42.     private   void  connect(String targetIpAddress,  int  targetPort)  throws  IOException {  
  43.         setTargetIpAddress(targetIpAddress);  
  44.         setTargetPort(targetPort);  
  45.         if (socket ==  null )  
  46.             socket = new  Socket(targetIpAddress, targetPort);  
  47.     }  
  48.   
  49.     /**  
  50.      * 这是对外接口。发送命令,接收反馈和接收message放两个线程,  
  51.      * 发送命令并接收反馈是短连接,所以每次执行成功后,将销毁socket并终止线程,  
  52.      * 接收message是长连接,所以可能会new出n个线程,建议对接收message的线程做缓存  
  53.      * @param commandType String 命令类型  
  54.      * @param commandContent String 命令内容  
  55.      * @param targetIP String 目标ip  
  56.      * @param targetPort int 目标端口  
  57.      */   
  58.     public   static   void  request(String commandType, String commandContent, String targetIP,  int  targetPort) {  
  59.         if  (commandType.equalsIgnoreCase(MessageFactory.SCAN_COMMAND)) {  
  60.             sf.new  GetMessageSocketThread(commandType, commandContent, targetIP, targetPort);  
  61.         } else  {  
  62.             sf.new  RequestSocketThread(commandType, commandContent, targetIP, targetPort);  
  63.         }  
  64.     }  
  65.   
  66.     /**  
  67.      * 发送请求  
  68.      * @param commandType String 命令类型  
  69.      * @param commandContent String 命令内容  
  70.      * @param targetIp String 目标ip  
  71.      */   
  72.     private   void  sendRequest(String commandType, String commandContent, String targetIp) {  
  73.         OutputStream os = null ;  
  74.         BufferedOutputStream bs = null ;  
  75.         try  {  
  76.             os = socket.getOutputStream();  
  77.             bs = new  BufferedOutputStream(os);  
  78.             char [] message = MessageFactory.makeRequestMessage(targetIp, commandType, commandContent, MessageFactory.COMMAND_TRADE_CODE, MessageFactory.RIGHT_COMMAND, MessageFactory.MESSAGE_END_FLAG);  
  79.             for  ( int  i =  0 ; i < message.length; i++)  
  80.                 bs.write(new  String(message).getBytes(), i,  1 );  
  81.             bs.flush();  
  82.             SwingUtils.appendLog(MainForm.jTextArea, "发送请求:'"  + commandType +  "' '"  + commandContent +  "' '"  + targetIp +  "'" , ReadConfig.commandStateShowLineCount);  
  83.         } catch  (IOException e) {  
  84.             SwingUtils.appendLog(MainForm.jTextArea, "Error!!! 发送请求:'"  + commandType +  "' '"  + commandContent +  "' '"  + targetIp +  "'失败!! "  + e.getMessage(), ReadConfig.commandStateShowLineCount);  
  85.             e.printStackTrace();  
  86.         } catch  (Exception e) {  
  87.             e.printStackTrace();  
  88.         } finally  {  
  89.         }  
  90.     }  
  91.   
  92.     /**  
  93.      * 获得反馈  
  94.      *   
  95.      * @return 如果成功获得反馈,则返回true;否则返回false  
  96.      */   
  97.     private   boolean  getResponse() {  
  98.         InputStream is = null ;  
  99.         DataInputStream di = null ;  
  100.         boolean  returnFlag =  false ;  
  101.         try  {  
  102.             is = socket.getInputStream();  
  103.             di = new  DataInputStream(is);  
  104.             byte [] temp =  new   byte [ 1 ];  
  105.             int  flag =  0 ;  
  106.             ArrayList tempByteList = new  ArrayList();  
  107.             int  i =  0 ;  
  108.             while  (flag != - 1 ) {  
  109.                 i++;  
  110.                 flag = di.read(temp = new   byte [ 1 ]);  
  111.                 if  (flag != - 1 )  
  112.                     tempByteList.add(temp);  
  113.                 if  (i ==  38 )  
  114.                     break ;  
  115.             }  
  116.             if  (i ==  1 ) {  
  117.                 SwingUtils.Error("未收到response!!!" );  
  118.                 return   false ;  
  119.             }  
  120.             MessageHead messageHead = MessageFactory.readHead(tempByteList);  
  121.   
  122.             SwingUtils.appendLog(MainForm.jTextArea, "收到 response" , ReadConfig.commandStateShowLineCount);  
  123.   
  124.             tempByteList = new  ArrayList();  
  125.             i = 0 ;  
  126.             while  (flag != - 1 ) {  
  127.                 i++;  
  128.                 flag = di.read(temp = new   byte [ 1 ]);  
  129.                 if  (flag != - 1 )  
  130.                     tempByteList.add(temp);  
  131.                 if  (i ==  26 )  
  132.                     break ;  
  133.             }  
  134.             byte [] length =  new   byte [ 4 ];  
  135.             di.read(length);  
  136.             int  len = Integer.parseInt( new  String(length, MessageFactory.DEFAULT_CHAR_SET).trim());  
  137.             flag = 0 ;  
  138.             for  ( int  j =  0 ; j < (len +  37 ); j++) {  
  139.                 flag = di.read(temp = new   byte [ 1 ]);  
  140.                 if  (flag == - 1 )  
  141.                     break ;  
  142.                 tempByteList.add(temp);  
  143.             }  
  144.   
  145.             ResponseMessage rm = MessageFactory.readResponseMessage(tempByteList, len);  
  146.   
  147.             if  (messageHead.getErrorCode().equals(MessageFactory.SUCCESS))  
  148.                 returnFlag = true ;  
  149.             else   
  150.                 SwingUtils.Error("errorCode: "  + messageHead.getErrorCode() +  "; content: "  + rm.getCommandContent());  
  151.         } catch  (IOException e) {  
  152.             e.printStackTrace();  
  153.         } finally  {  
  154.         }  
  155.         return  returnFlag;  
  156.     }  
  157.   
  158.     /**  
  159.      * 分发消息的方法,将消息按进程名发送到对应的消息缓存   
  160.      *  
  161.      * 消息缓存ListenerInvoke.messageMap,key = machineName +  
  162.      * '|' + programName + '|' + processId, value = messageList  
  163.      * 存放messageMap里面的键名的List -- ListenerInvoke.messageMapKeyList  
  164.      * 进程状态缓存ListenerInvoke.processStateMap, key = machineName + '|' +  
  165.      * programName + '|' + processId, value = String  
  166.      *   
  167.      * @param message Message  
  168.      */   
  169.     private   void  distributeMess(Message message) {  
  170.         String machineName = message.getMachineName();  
  171.         String programName = message.getProgramName();  
  172.         String processId = message.getProcessId();  
  173.         String content = message.getContent();  
  174.         String key = machineName + '|'  + programName +  '|'  + processId;  
  175.         key = key.trim();  
  176.         ArrayList messageList = null ;  
  177.         if  (ListenerInvoke.messageMap.get(key) ==  null ) {  
  178.             synchronized  (ListenerInvoke.messageMap) {  
  179.                 if  (ListenerInvoke.messageMap.get(key) ==  null ) {  
  180.                     messageList = new  ArrayList();  
  181.                     messageList.add(content);             
  182.                     ListenerInvoke.messageMap.put(key, messageList);  
  183.                 }  
  184.             }  
  185.         } else  {  
  186.             messageList = (ArrayList) ListenerInvoke.messageMap.get(key);  
  187.             synchronized  (messageList) {  
  188.                 if  (ListenerInvoke.messageMap.get(key) !=  null ) {  
  189.                     messageList.add(content);  
  190.                     if  (!ReadConfig.threadDeleteMessCacheOrFIFO  
  191.                             && messageList.size() >= ReadConfig.messageCacheSizeLimit)  
  192.                         messageList.remove(0 );  
  193.                 }  
  194.             }  
  195.         }  
  196.         if  (!ListenerInvoke.messageMapKeyList.contains(key)) {  
  197.             synchronized  (ListenerInvoke.messageMapKeyList) {  
  198.                 if  (!ListenerInvoke.messageMapKeyList.contains(key))  
  199.                     ListenerInvoke.messageMapKeyList.add(key);  
  200.             }  
  201.         }  
  202.     }  
  203.   
  204.     /**  
  205.      * 接收message  
  206.      * @return Message  
  207.      */   
  208.     private   boolean  getMessage() {  
  209.         InputStream is = null ;  
  210.         DataInputStream di = null ;  
  211.         Message message = null ;  
  212.         try  {  
  213.             if  ( this .socket ==  null )   return   false ;  
  214.             is = this .socket.getInputStream();  
  215.             if  (is ==  null )   return   false ;  
  216.             di = new  DataInputStream(is);  
  217.             byte [] temp =  new   byte [ 1 ];  
  218.             int  flag =  0 ;  
  219.             ArrayList tempByteList = new  ArrayList();  
  220.             int  i =  0 ;  
  221.             while  (flag != - 1 ) {  
  222.                 i++;  
  223.                 flag = di.read(temp = new   byte [ 1 ]);  
  224.                 if  (flag != - 1 )  
  225.                     tempByteList.add(temp);  
  226.                 if  (i ==  38 )  
  227.                     break ;  
  228.             }  
  229.             if  (i ==  1 )   return   false ;  
  230.   
  231.             tempByteList = new  ArrayList();  
  232.             i = 0 ;  
  233.             while  (flag != - 1 ) {  
  234.                 i++;  
  235.                 flag = di.read(temp = new   byte [ 1 ]);  
  236.                 if  (flag != - 1 )  
  237.                     tempByteList.add(temp);  
  238.                 if  (i ==  74 )  
  239.                     break ;  
  240.             }  
  241.             byte [] length =  new   byte [ 4 ];  
  242.             di.read(length);  
  243.             int  len = Integer.parseInt( new  String(length,  
  244.                     MessageFactory.DEFAULT_CHAR_SET).trim());  
  245.             flag = 0 ;  
  246.             for  ( int  j =  0 ; j < len; j++) {  
  247.                 flag = di.read(temp = new   byte [ 1 ]);  
  248.                 if  (flag == - 1 )  
  249.                     break ;  
  250.                 tempByteList.add(temp);  
  251.             }  
  252.             message = MessageFactory.readMessage(tempByteList, len);  
  253.             SwingUtils.appendLog(MainForm.jTextArea, "收到新 Message" ,  
  254.                     ReadConfig.commandStateShowLineCount);  
  255.             distributeMess(message);// 分发message   
  256.         } catch  (IOException e) {  
  257.             e.printStackTrace();  
  258.         } finally  {  
  259.         }  
  260.         return   true ;  
  261.     }  
  262.   
  263.     /**  
  264.      * 负责发送请求接收反馈的内部线程类,每new一个RequestSocketThread线程,  
  265.      * 就new一个socket,建立一条专属连接,成功接收反馈后将销毁socket,终止线程。  
  266.      * 将发送请求,接收反馈放进内部线程处理,是为了防止套接字阻塞造成主线程挂死。  
  267.      * @author cuishen  
  268.      * @version 1.2  
  269.      */   
  270.     class  RequestSocketThread  implements  Runnable {  
  271.         private  SocketFactory socketFactory;  
  272.         private  String commandType =  null ;  
  273.         private  String commandContent =  null ;  
  274.         private  String targetIP =  null ;  
  275.         Thread t;  
  276.   
  277.         public  RequestSocketThread(String commandType, String commandContent, String targetIP,  int  targetPort) {  
  278.             this .socketFactory =  new  SocketFactory();  
  279.             try  {  
  280.                 this .socketFactory.connect(ReadConfig.targetIpAddress, ReadConfig.targetPort);  
  281.             } catch  (UnknownHostException e) {  
  282.                 SwingUtils.Error("主机 IP 地址无法确定,无法建立连接! targetIP="  + ReadConfig.targetIpAddress +  ", targetPort="  + ReadConfig.targetPort);  
  283.                 e.printStackTrace();  
  284.             } catch  (IOException e) {  
  285.                 SwingUtils.Error("访问被拒绝,无法建立连接,请检查网络! targetIP="  + ReadConfig.targetIpAddress +  ", targetPort="  + ReadConfig.targetPort);  
  286.                 e.printStackTrace();  
  287.             }  
  288.             this .commandType = commandType;  
  289.             this .commandContent = commandContent;  
  290.             this .targetIP = targetIP;  
  291.             t = new  Thread( this );  
  292.             t.start();  
  293.         }  
  294.   
  295.         public   void  run() {  
  296.             this .socketFactory.sendRequest(commandType, commandContent, targetIP);  
  297.             this .socketFactory.getResponse();  
  298.             stopThread();  
  299.         }  
  300.   
  301.         public   void  stopThread() {  
  302.             try  {  
  303.                 this .commandType =  null ;  
  304.                 this .commandContent =  null ;  
  305.                 this .targetIP =  null ;  
  306.                 socketFactory.closeSocket();  
  307.                 socketFactory = null ;  
  308.                 this .t.join( 100 );  
  309.             } catch  (InterruptedException e) {  
  310.                 e.printStackTrace();  
  311.             } finally  {  
  312.                 t = null ;  
  313.             }  
  314.         }  
  315.     }  
  316.   
  317.     /**  
  318.      * 负责接收message的内部线程类,每new一个GetMessageSocketThread线程,  
  319.      * 就new一个socket,建立一条专属TCP/IP 连接,getMessage是长连接,所以建议  
  320.      * 将该线程放入缓存方便管理  
  321.      * @author cuishen  
  322.      * @version 1.2  
  323.      */   
  324.     class  GetMessageSocketThread  implements  Runnable {  
  325.         private  SocketFactory socketFactory;  
  326.         private  String commandType =  null ;  
  327.         private  String commandContent =  null ;  
  328.         private  String targetIP =  null ;  
  329.         Thread t;  
  330.         private   boolean  flag =  false ;  
  331.         private   boolean  ifGetResponse =  true ;  
  332.         private   boolean  ifGetMessage =  true ;  
  333.         private   boolean  ifSendRequest =  true ;  
  334.         private   boolean  ifCycle =  true ;  
  335.   
  336.         public  GetMessageSocketThread(String commandType, String commandContent, String targetIP,  int  targetPort) {  
  337.               
  338.             this .socketFactory =  new  SocketFactory();  
  339.             try  {  
  340.                 this .socketFactory.connect(ReadConfig.targetIpAddress, ReadConfig.targetPort);  
  341.             } catch  (UnknownHostException e) {  
  342.                 SwingUtils.Error("主机 IP 地址无法确定,无法建立连接! targetIP="   
  343.                         + ReadConfig.targetIpAddress + ", targetPort="   
  344.                         + ReadConfig.targetPort);  
  345.                 e.printStackTrace();  
  346.             } catch  (IOException e) {  
  347.                 SwingUtils.Error("访问被拒绝,无法建立连接,请检查网络! targetIP="   
  348.                         + ReadConfig.targetIpAddress + ", targetPort="   
  349.                         + ReadConfig.targetPort);  
  350.                 e.printStackTrace();  
  351.             }  
  352.             this .commandType = commandType;  
  353.             this .commandContent = commandContent;  
  354.             this .targetIP = targetIP;  
  355.             t = new  Thread( this );  
  356.             t.start();  
  357.         }  
  358.   
  359.         public   void  run() {  
  360.             while  (ifCycle) {  
  361.                 if  (ifSendRequest) {  
  362.                     this .socketFactory.sendRequest(commandType, commandContent, targetIP);  
  363.                     ifSendRequest = false ;  
  364.                 }  
  365.                 if  (ifGetResponse) {  
  366.                     flag = socketFactory.getResponse();  
  367.                     ifGetResponse = false ;  
  368.                 }  
  369.                 if  (flag && ifGetMessage && socketFactory.socket !=  null ) {  
  370.                     if  (!socketFactory.getMessage()) {  
  371.                         try  {  
  372.                             Thread.sleep(ReadConfig.getMessageThreadSleep);  
  373.                         } catch  (InterruptedException e) {  
  374.                             e.printStackTrace();  
  375.                         }  
  376.                     }  
  377.                 }  
  378.             }  
  379.         }  
  380.   
  381.         public   void  stopThread() {  
  382.             try  {  
  383.                 this .commandType =  null ;  
  384.                 this .commandContent =  null ;  
  385.                 this .targetIP =  null ;  
  386.                 ifGetMessage = false ;  
  387.                 ifCycle = false ;  
  388.                 socketFactory.closeSocket();  
  389.                 socketFactory = null ;  
  390.                 this .t.join( 100 );  
  391.             } catch  (InterruptedException e) {  
  392.                 e.printStackTrace();  
  393.             } finally  {  
  394.                 t = null ;  
  395.             }  
  396.         }  
  397.     }  
  398.   
  399.     /**  
  400.      * 关闭套接字  
  401.      */   
  402.     private   void  closeSocket() {  
  403.         try  {  
  404.             if  (!socket.isClosed())  
  405.                 socket.close();  
  406.             socket = null ;  
  407.         } catch  (IOException e) {  
  408.             e.printStackTrace();  
  409.         }  
  410.     }  
  411.   
  412.     /**  
  413.      * @return the targetIpAddress  
  414.      */   
  415.     public  String getTargetIpAddress() {  
  416.         return  targetIpAddress;  
  417.     }  
  418.   
  419.     /**  
  420.      * @param targetIpAddress  
  421.      *            the targetIpAddress to set  
  422.      */   
  423.     public   void  setTargetIpAddress(String targetIpAddress) {  
  424.         this .targetIpAddress = targetIpAddress;  
  425.     }  
  426.   
  427.     /**  
  428.      * @return the targetPort  
  429.      */   
  430.     public   int  getTargetPort() {  
  431.         return  targetPort;  
  432.     }  
  433.   
  434.     /**  
  435.      * @param targetPort  
  436.      *            the targetPort to set  
  437.      */   
  438.     public   void  setTargetPort( int  targetPort) {  
  439.         this .targetPort = targetPort;  
  440.     }  
  441.   
  442. }  
package com.sse.monitor.serv;

import java
.io.DataInputStream;
import java
.io.IOException;
import java
.io.InputStream;
import java
.io.OutputStream;
import java
.io.BufferedOutputStream;

import java
.net.Socket;
import java
.net.UnknownHostException;
import java
.util.ArrayList;

import com.sse.monitor.bean.Message;
import com.sse.monitor.bean.MessageHead;
import com.sse.monitor.bean.ResponseMessage;
import com.sse.monitor.form.ListenerInvoke;
import com.sse.monitor.form.MainForm;
import com.sse.monitor.util.SwingUtils;

/**
 * Socket套接字工厂,对外接口是静态方法 SocketFactory.request(String, String, String, int) 
 * Copyright: Copyright (c) 2008 
 * Company: conserv
 * @author cuishen
 * @version 1.3
 */
public class SocketFactory {
	private Socket socket = null;
	private String targetIpAddress = null;
	private int targetPort = 0;
	private static SocketFactory sf = new SocketFactory();

	public SocketFactory() {
	}

	/**
	 * 建立一条TCP/IP
连接
	 * @param targetIpAddress String 目标ip地址
	 * @param targetPort String 目标端口
	 * @throws IOException
	 */
	private void connect(String targetIpAddress, int targetPort) throws IOException {
		setTargetIpAddress(targetIpAddress);
		setTargetPort(targetPort);
		if(socket == null)
			socket = new Socket(targetIpAddress, targetPort);
	}

	/**
	 * 这是对外接口。发送命令,接收反馈和接收message放两个线程,
	 * 发送命令并接收反馈是短连接,所以每次执行成功后,将销毁socket并终止线程,
	 * 接收message是长连接,所以可能会new出n个线程,建议对接收message的线程做缓存
	 * @param commandType String 命令类型
	 * @param commandContent String 命令内容
	 * @param targetIP String 目标ip
	 * @param targetPort int 目标端口
	 */
	public static void request(String commandType, String commandContent, String targetIP, int targetPort) {
		if (commandType.equalsIgnoreCase(MessageFactory.SCAN_COMMAND)) {
			sf.new GetMessageSocketThread(commandType, commandContent, targetIP, targetPort);
		} else {
			sf.new RequestSocketThread(commandType, commandContent, targetIP, targetPort);
		}
	}

	/**
	 * 发送请求
	 * @param commandType String 命令类型
	 * @param commandContent String 命令内容
	 * @param targetIp String 目标ip
	 */
	private void sendRequest(String commandType, String commandContent, String targetIp) {
		OutputStream os = null;
		BufferedOutputStream bs = null;
		try {
			os = socket.getOutputStream();
			bs = new BufferedOutputStream(os);
			char[] message = MessageFactory.makeRequestMessage(targetIp, commandType, commandContent, MessageFactory.COMMAND_TRADE_CODE, MessageFactory.RIGHT_COMMAND, MessageFactory.MESSAGE_END_FLAG);
			for (int i = 0; i < message.length; i++)
				bs.write(new String(message).getBytes(), i, 1);
			bs.flush();
			SwingUtils.appendLog(MainForm.jTextArea, "发送请求:'" + commandType + "' '" + commandContent + "' '" + targetIp + "'", ReadConfig.commandStateShowLineCount);
		} catch (IOException e) {
			SwingUtils.appendLog(MainForm.jTextArea, "Error!!! 发送请求:'" + commandType + "' '" + commandContent + "' '" + targetIp + "'失败!! " + e.getMessage(), ReadConfig.commandStateShowLineCount);
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
		}
	}

	/**
	 * 获得反馈
	 * 
	 * @return 如果成功获得反馈,则返回true;否则返回false
	 */
	private boolean getResponse() {
		InputStream is = null;
		DataInputStream di = null;
		boolean returnFlag = false;
		try {
			is = socket.getInputStream();
			di = new DataInputStream(is);
			byte[] temp = new byte[1];
			int flag = 0;
			ArrayList tempByteList = new ArrayList();
			int i = 0;
			while (flag != -1) {
				i++;
				flag = di.read(temp = new byte[1]);
				if (flag != -1)
					tempByteList.add(temp);
				if (i == 38)
					break;
			}
			if (i == 1) {
				SwingUtils.Error("未收到response!!!");
				return false;
			}
			MessageHead messageHead = MessageFactory.readHead(tempByteList);

			SwingUtils.appendLog(MainForm.jTextArea, "收到 response", ReadConfig.commandStateShowLineCount);

			tempByteList = new ArrayList();
			i = 0;
			while (flag != -1) {
				i++;
				flag = di.read(temp = new byte[1]);
				if (flag != -1)
					tempByteList.add(temp);
				if (i == 26)
					break;
			}
			byte[] length = new byte[4];
			di.read(length);
			int len = Integer.parseInt(new String(length, MessageFactory.DEFAULT_CHAR_SET).trim());
			flag = 0;
			for (int j = 0; j < (len + 37); j++) {
				flag = di.read(temp = new byte[1]);
				if (flag == -1)
					break;
				tempByteList.add(temp);
			}

			ResponseMessage rm = MessageFactory.readResponseMessage(tempByteList, len);

			if (messageHead.getErrorCode().equals(MessageFactory.SUCCESS))
				returnFlag = true;
			else
				SwingUtils.Error("errorCode: " + messageHead.getErrorCode() + "; content: " + rm.getCommandContent());
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
		}
		return returnFlag;
	}

	/**
	 * 分发消息的方法,将消息按进程名发送到对应的消息缓存 
	 *
	 * 消息缓存ListenerInvoke.messageMap,key = machineName +
	 * '|' + programName + '|' + processId, value = messageList
	 * 存放messageMap里面的键名的List -- ListenerInvoke.messageMapKeyList
	 * 进程状态缓存ListenerInvoke.processStateMap, key = machineName + '|' +
	 * programName + '|' + processId, value = String
	 * 
	 * @param message Message
	 */
	private void distributeMess(Message message) {
		String machineName = message.getMachineName();
		String programName = message.getProgramName();
		String processId = message.getProcessId();
		String content = message.getContent();
		String key = machineName + '|' + programName + '|' + processId;
		key = key.trim();
		ArrayList messageList = null;
		if (ListenerInvoke.messageMap.get(key) == null) {
			synchronized (ListenerInvoke.messageMap) {
				if (ListenerInvoke.messageMap.get(key) == null) {
					messageList = new ArrayList();
					messageList.add(content);			
					ListenerInvoke.messageMap.put(key, messageList);
				}
			}
		} else {
			messageList = (ArrayList) ListenerInvoke.messageMap.get(key);
			synchronized (messageList) {
				if (ListenerInvoke.messageMap.get(key) != null) {
					messageList.add(content);
					if (!ReadConfig.threadDeleteMessCacheOrFIFO
							&& messageList.size() >= ReadConfig.messageCacheSizeLimit)
						messageList.remove(0);
				}
			}
		}
		if (!ListenerInvoke.messageMapKeyList.contains(key)) {
			synchronized (ListenerInvoke.messageMapKeyList) {
				if (!ListenerInvoke.messageMapKeyList.contains(key))
					ListenerInvoke.messageMapKeyList.add(key);
			}
		}
	}

	/**
	 * 接收message
	 * @return Message
	 */
	private boolean getMessage() {
		InputStream is = null;
		DataInputStream di = null;
		Message message = null;
		try {
			if (this.socket == null)  return false;
			is = this.socket.getInputStream();
			if (is == null)  return false;
			di = new DataInputStream(is);
			byte[] temp = new byte[1];
			int flag = 0;
			ArrayList tempByteList = new ArrayList();
			int i = 0;
			while (flag != -1) {
				i++;
				flag = di.read(temp = new byte[1]);
				if (flag != -1)
					tempByteList.add(temp);
				if (i == 38)
					break;
			}
			if (i == 1)  return false;

			tempByteList = new ArrayList();
			i = 0;
			while (flag != -1) {
				i++;
				flag = di.read(temp = new byte[1]);
				if (flag != -1)
					tempByteList.add(temp);
				if (i == 74)
					break;
			}
			byte[] length = new byte[4];
			di.read(length);
			int len = Integer.parseInt(new String(length,
					MessageFactory.DEFAULT_CHAR_SET).trim());
			flag = 0;
			for (int j = 0; j < len; j++) {
				flag = di.read(temp = new byte[1]);
				if (flag == -1)
					break;
				tempByteList.add(temp);
			}
			message = MessageFactory.readMessage(tempByteList, len);
			SwingUtils.appendLog(MainForm.jTextArea, "收到新 Message",
					ReadConfig.commandStateShowLineCount);
			distributeMess(message);// 分发message
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
		}
		return true;
	}

	/**
	 * 负责发送请求接收反馈的内部线程类,每new一个RequestSocketThread线程,
	 * 就new一个socket,建立一条专属连接,成功接收反馈后将销毁socket,终止线程。
	 * 将发送请求,接收反馈放进内部线程处理,是为了防止套接字阻塞造成主线程挂死。
	 * @author cuishen
	 * @version 1.2
	 */
	class RequestSocketThread implements Runnable {
		private SocketFactory socketFactory;
		private String commandType = null;
		private String commandContent = null;
		private String targetIP = null;
		Thread t;

		public RequestSocketThread(String commandType, String commandContent, String targetIP, int targetPort) {
			this.socketFactory = new SocketFactory();
			try {
				this.socketFactory.connect(ReadConfig.targetIpAddress, ReadConfig.targetPort);
			} catch (UnknownHostException e) {
				SwingUtils.Error("主机 IP 地址无法确定,无法建立连接! targetIP=" + ReadConfig.targetIpAddress + ", targetPort=" + ReadConfig.targetPort);
				e.printStackTrace();
			} catch (IOException e) {
				SwingUtils.Error("访问被拒绝,无法建立连接,请检查网络! targetIP=" + ReadConfig.targetIpAddress + ", targetPort=" + ReadConfig.targetPort);
				e.printStackTrace();
			}
			this.commandType = commandType;
			this.commandContent = commandContent;
			this.targetIP = targetIP;
			t = new Thread(this);
			t.start();
		}

		public void run() {
			this.socketFactory.sendRequest(commandType, commandContent, targetIP);
			this.socketFactory.getResponse();
			stopThread();
		}

		public void stopThread() {
			try {
				this.commandType = null;
				this.commandContent = null;
				this.targetIP = null;
				socketFactory.closeSocket();
				socketFactory = null;
				this.t.join(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally {
				t = null;
			}
		}
	}

	/**
	 * 负责接收message的内部线程类,每new一个GetMessageSocketThread线程,
	 * 就new一个socket,建立一条专属TCP/IP
连接,getMessage是长连接,所以建议
	 * 将该线程放入缓存方便管理
	 * @author cuishen
	 * @version 1.2
	 */
	class GetMessageSocketThread implements Runnable {
		private SocketFactory socketFactory;
		private String commandType = null;
		private String commandContent = null;
		private String targetIP = null;
		Thread t;
		private boolean flag = false;
		private boolean ifGetResponse = true;
		private boolean ifGetMessage = true;
		private boolean ifSendRequest = true;
		private boolean ifCycle = true;

		public GetMessageSocketThread(String commandType, String commandContent, String targetIP, int targetPort) {
			
			this.socketFactory = new SocketFactory();
			try {
				this.socketFactory.connect(ReadConfig.targetIpAddress, ReadConfig.targetPort);
			} catch (UnknownHostException e) {
				SwingUtils.Error("主机 IP 地址无法确定,无法建立连接! targetIP="
						+ ReadConfig.targetIpAddress + ", targetPort="
						+ ReadConfig.targetPort);
				e.printStackTrace();
			} catch (IOException e) {
				SwingUtils.Error("访问被拒绝,无法建立连接,请检查网络! targetIP="
						+ ReadConfig.targetIpAddress + ", targetPort="
						+ ReadConfig.targetPort);
				e.printStackTrace();
			}
			this.commandType = commandType;
			this.commandContent = commandContent;
			this.targetIP = targetIP;
			t = new Thread(this);
			t.start();
		}

		public void run() {
			while (ifCycle) {
				if (ifSendRequest) {
					this.socketFactory.sendRequest(commandType, commandContent, targetIP);
					ifSendRequest = false;
				}
				if (ifGetResponse) {
					flag = socketFactory.getResponse();
					ifGetResponse = false;
				}
				if (flag && ifGetMessage && socketFactory.socket != null) {
					if (!socketFactory.getMessage()) {
						try {
							Thread.sleep(ReadConfig.getMessageThreadSleep);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
			}
		}

		public void stopThread() {
			try {
				this.commandType = null;
				this.commandContent = null;
				this.targetIP = null;
				ifGetMessage = false;
				ifCycle = false;
				socketFactory.closeSocket();
				socketFactory = null;
				this.t.join(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally {
				t = null;
			}
		}
	}

	/**
	 * 关闭套接字
	 */
	private void closeSocket() {
		try {
			if (!socket.isClosed())
				socket.close();
			socket = null;
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * @return the targetIpAddress
	 */
	public String getTargetIpAddress() {
		return targetIpAddress;
	}

	/**
	 * @param targetIpAddress
	 *            the targetIpAddress to set
	 */
	public void setTargetIpAddress(String targetIpAddress) {
		this.targetIpAddress = targetIpAddress;
	}

	/**
	 * @return the targetPort
	 */
	public int getTargetPort() {
		return targetPort;
	}

	/**
	 * @param targetPort
	 *            the targetPort to set
	 */
	public void setTargetPort(int targetPort) {
		this.targetPort = targetPort;
	}

}



以上是Socket编程,ServerSocket在项目里没有用到,但是我也写了个包装类供参考

Java 代码
  1. package  com.sse.monitor.serv;  
  2.   
  3. import  java .io.IOException;  
  4. import  java .net.ServerSocket;  
  5. import  java .net.Socket;  
  6.   
  7. /**  
  8.  * 服务器套接字工厂  
  9.  * Copyright: Copyright (c) 2008  
  10.  * @author cuishen  
  11.  * @version 1.0  
  12.  */   
  13. public   class  ServerSocketFactory {  
  14.     private   static  ServerSocket server;  
  15.     private   static  Socket client;  
  16.     private   boolean  ifRunServer =  true ;  
  17.       
  18.     public   void  runServer( int  port)  throws  IOException {  
  19.         //本地建立一个套接字服务器,等待其他机器访问   
  20.         server = new  ServerSocket(port);  
  21.         System.out.println("Socket Server Start..." );  
  22.         new  ServerThread();  
  23.     }  
  24.       
  25.   
  26.     class  ServerThread  implements  Runnable {  
  27.         Thread t;  
  28.           
  29.         public  ServerThread() {  
  30.             t = new  Thread( this );  
  31.             t.start();  
  32.         }  
  33.   
  34.         public   void  run() {  
  35.             try  {  
  36.                 while (ifRunServer) {  
  37.                     if (client ==  null ) client = server.accept();  
  38.                     if (client !=  null//getMessage();   
  39.                     Thread.sleep(ReadConfig.serverThreadSleep);  
  40.                 }  
  41.             } catch  (InterruptedException e) {  
  42.                 e.printStackTrace();  
  43.             }   
  44.             catch  (IOException e) {  
  45.                 e.printStackTrace();  
  46.             }  
  47.         }  
  48.         public   void  stopThread() {  
  49.             try  {  
  50.                 ifRunServer = false ;  
  51.                 this .t.join( 100 );  
  52.             } catch  (InterruptedException ex) {  
  53.                 System.out.println("socket服务器线程终止异常!!!" );  
  54.             } finally  {  
  55.                 t = null ;  
  56.             }  
  57.         }  
  58.     }  
  59. }  
package com.sse.monitor.serv;

import java
.io.IOException;
import java
.net.ServerSocket;
import java
.net.Socket;

/**
 * 服务器套接字工厂
 * Copyright: Copyright (c) 2008
 * @author cuishen
 * @version 1.0
 */
public class ServerSocketFactory {
	private static ServerSocket server;
	private static Socket client;
	private boolean ifRunServer = true;
	
	public void runServer(int port) throws IOException {
		//本地建立一个套接字服务器,等待其他机器访问
		server = new ServerSocket(port);
		System.out.println("Socket Server Start...");
		new ServerThread();
	}
	

	class ServerThread implements Runnable {
		Thread t;
	    
		public ServerThread() {
	        t = new Thread(this);
	        t.start();
	    }

	    public void run() {
	        try {
	            while(ifRunServer) {
	            	if(client == null) client = server.accept();
	            	if(client != null) //getMessage();
	                Thread.sleep(ReadConfig.serverThreadSleep);
	            }
	        } catch (InterruptedException e) {
	            e.printStackTrace();
	        } 
	    	catch (IOException e) {
				e.printStackTrace();
			}
	    }
	    public void stopThread() {
	        try {
	        	ifRunServer = false;
	        	this.t.join(100);
	        } catch (InterruptedException ex) {
	            System.out.println("socket服务器线程终止异常!!!");
	        } finally {
	        	t = null;
	        }
	    }
	}
}



Socket编程就是运用Socket或者ServerSocket类搭配线程来使用(由于TCP/IP 属 于可靠性传输,不会丢包)。可能会因为在发送请求或者接受消息时Socket阻塞而导致主线程挂死,因此发送请求、接收消息的方法要放进子线程里处理;对 于同一目标ip和端口,在同一个子线程里只能new一个Socket,也就是说,要对同一地址建立多条连接,就要开启多个线程。而且注意连接可能会因作用 不同分长连接和短连接,要分别处理,本项目中发送请求和接受message就分别属于短连接和长连接,因此分别开发了 RequestSocketThread和GetMessageSocketThread两个子线程区分对待。可以同时开发个Message类来封装打包 和解包消息的方法(项目中开发MessageFactory.java ),方便调用

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值