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


    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套接字工厂,对外接口是静态方法request(String, String, String, int) 
     * Copyright: Copyright (c) 2008 
     * Company: conserv
     * @author cuishen
     * @version 1.2
     */
    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 messGrade = message.getMessageGrade();
    		String content = message.getContent();
    		String key = machineName + '|' + programName + '|' + processId;
    		ArrayList messageList = (ArrayList) ListenerInvoke.messageMap.get(key);
    		if (messageList == null) {
    			messageList = new ArrayList();
    			messageList.add(content);
    			ListenerInvoke.messageMap.put(key, messageList);
    		} else {
    			synchronized (messageList) {
    				messageList.add(content);
    				if (!ReadConfig.threadDeleteMessCacheOrFIFO
    						&& messageList.size() >= ReadConfig.messageCacheSizeLimit)
    					messageList.remove(0);
    			}
    		}
    		ListenerInvoke.processStateMap.put(key, messGrade);
    		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 = false;
    		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
    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
    14. private static
    15. private static
    16. private boolean ifRunServer = true;  
    17.       
    18. public void runServer(int port) throws
    19. //本地建立一个套接字服务器,等待其他机器访问
    20. new
    21. "Socket Server Start...");  
    22. new
    23.     }  
    24.       
    25.   
    26. class ServerThread implements
    27.         Thread t;  
    28.           
    29. public
    30. new Thread(this);  
    31.             t.start();  
    32.         }  
    33.   
    34. public void
    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
    42.                 e.printStackTrace();  
    43.             }   
    44. catch
    45.                 e.printStackTrace();  
    46.             }  
    47.         }  
    48. public void
    49. try
    50. false;  
    51. this.t.join(100);  
    52. catch
    53. "socket服务器线程终止异常!!!");  
    54. finally
    55. 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),方便调用