socket 通信大全


下面就是Java Socket通信技术在解决收发线程互斥的代码介绍。


1.package com.bill99.svr;  
2.import java.io.IOException;  
3.import java.io.InputStream;  
4.import java.io.OutputStream;  
5.import java.net.InetSocketAddress;  
6.import java.net.Socket;  
7.import java.net.SocketException;  
8.import java.net.SocketTimeoutException;  
9.import java.text.SimpleDateFormat;  
10.import java.util.Date;  
11.import java.util.Properties;  
12.import java.util.Timer;  
13.import java.util.TimerTask;  
14.import java.util.concurrent.ConcurrentHashMap;  
15.import java.util.concurrent.TimeUnit;  
16.import java.util.concurrent.locks.Condition;  
17.import java.util.concurrent.locks.ReentrantLock;  
18.import org.apache.log4j.Logger;  
19./**  
20.
*<p>title: socket通信包装类</p>  

21.
*<p>Description: </p>  

22.
*<p>CopyRight: CopyRight (c) 2009</p>  

23.
*<p>Company: 99bill.com</p>  

24.
*<p>Create date: 2009-10-14</P>  

25.
*author sunnylocus<A href="mailto:[email protected]">  

26.
</A> * v0.10 2009-10-14 初类  

27.* v0.11 2009-11-12 对命令收发逻辑及收发线程互斥机制进行了优化,
处理命令速度由原来8~16个/秒提高到25~32个/秒  
28.*/ public class SocketConnection {  
29.private volatile Socket socket;  
30.
private int timeout = 1000*10; //超时时间,初始值10秒  

31.
private boolean isLaunchHeartcheck = false;//是否已启动心跳检测  

32.
private boolean isNetworkConnect = false; //网络是否已连接  

33.
private static String host = "";  

34.private static int port;  
35.
static InputStream inStream = null;  

36.
static OutputStream outStream = null;  

37.
private static Logger log =Logger.getLogger
(SocketConnection.class);  

38.
private static SocketConnection socketConnection = null;  

39.
private static java.util.Timer heartTimer=null;    

40.
//private final Map<String, Object> recMsgMap= Collections.
synchronizedMap(new HashMap<String, Object>());  

41.
private final ConcurrentHashMap<String, Object> recMsgMap
= new ConcurrentHashMap<String, Object>();  

42.
private static Thread receiveThread = null;  

43.
private final ReentrantLock lock = new ReentrantLock();  

44.private SocketConnection(){  
45.
Properties conf = new Properties();  

46.try {  
47.conf.load(SocketConnection.class.getResourceAsStream
("test.conf"));  
48.
this.timeout = Integer.valueOf(conf.getProperty("timeout"));  

49.init(conf.getProperty("ip"),Integer.valueOf
(conf.getProperty("port")));  
50.} catch(IOException e) {  
51.log.fatal("socket初始化异常!",e);  
52.throw new RuntimeException("socket初始化异常,请检查配置参数");  
53.}  
54.}  
55./**  
56.* 单态模式  
57.*/  
58.public static SocketConnection getInstance() {  
59.
if(socketConnection==null) {  

60.synchronized(SocketConnection.class) {  
61.
if(socketConnection==null) {  

62.
socketConnection = new SocketConnection();  

63.return socketConnection;  
64.}  
65.}  
66.}  
67.return socketConnection;  
68.}  
69.private void init(String host,int port) throws IOException {  
70.
InetSocketAddress addr = new InetSocketAddress(host,port);  

71.
socket = new Socket();  

72.synchronized (this) {  
73.log.info("【准备与"+addr+"建立连接】");  
74.socket.connect(addr, timeout);  
75.log.info("【与"+addr+"连接已建立】");  
76.
inStream = socket.getInputStream();  

77.
outStream = socket.getOutputStream();  

78.socket.setTcpNoDelay(true);//数据不作缓冲,立即发送  
79.socket.setSoLinger(true, 0);//socket关闭时,立即释放资源  
80.socket.setKeepAlive(true);  
81.socket.setTrafficClass(0x04|0x10);//高可靠性和最小延迟传输  
82.
isNetworkConnect=true;  

83.
receiveThread = new Thread(new ReceiveWorker());  

84.receiveThread.start();  
85.
SocketConnection.host=host;  

86.
SocketConnection.port=port;  

87.if(!isLaunchHeartcheck)  
88.launchHeartcheck();  
89.}  
90.}  
91./**  
92.* 心跳包检测  
93.*/  
94.private void launchHeartcheck() {  
95.
if(socket == null)  

96.throw new IllegalStateException("socket is not
established!");  
97.
heartTimer = new Timer();  

98.
isLaunchHeartcheck = true;  

99.heartTimer.schedule(new TimerTask() {  
100.public void run() {  
101.
String msgStreamNo = StreamNoGenerator.getStreamNo("kq");  

102.
int mstType =9999;//999-心跳包请求  

103.
SimpleDateFormat dateformate = new SimpleDateFormat
("yyyyMMddHHmmss");  

104.
String msgDateTime = dateformate.format(new Date());  

105.
int msgLength =38;//消息头长度  

106.
String commandstr = "00" +msgLength + mstType + msgStreamNo;  

107.
log.info("心跳检测包 -> IVR "+commandstr);  

108.
int reconnCounter = 1;  

109.while(true) {  
110.
String responseMsg =null;  

111.try {  
112.
responseMsg = readReqMsg(commandstr);  

113.} catch (IOException e) {  
114.log.error("IO流异常",e);  
115.reconnCounter ++;  
116.}  
117.if(responseMsg!=null) {  
118.
log.info("心跳响应包 <- IVR "+responseMsg);  

119.
reconnCounter = 1;  

120.break;  
121.} else {  
122.reconnCounter ++;  
123.}  
124.
if(reconnCounter >3) {//重连次数已达三次,判定网络连接中断,
重新建立连接。连接未被建立时不释放锁  

125.reConnectToCTCC(); break;  
126.}  
127.}  
128.}  
129.},1000 * 60*1,1000*60*2);  
130.}  
131./**  
132.* 重连与目标IP建立重连  
133.*/  
134.private void reConnectToCTCC() {  
135.new Thread(new Runnable(){  
136.public void run(){  
137.log.info("重新建立与"+host+":"+port+"的连接");  
138.//清理工作,中断计时器,中断接收线程,恢复初始变量  
139.heartTimer.cancel();  
140.
isLaunchHeartcheck=false;  

141.
isNetworkConnect = false;  

142.receiveThread.interrupt();  
143.try {  
144.socket.close();  
145.} catch (IOException e1) {log.error("重连时,关闭socket连
接发生IO流异常",e1);}  
146.//----------------  
147.synchronized(this){  
148.for(; ;){  
149.try {  
150.Thread.currentThread();  
151.Thread.sleep(1000 * 1);  
152.init(host,port);  
153.this.notifyAll();  
154.break ;  
155.} catch (IOException e) {  
156.log.error("重新建立连接未成功",e);  
157.} catch (InterruptedException e){  
158.log.error("重连线程中断",e);  
159.}  
160.}  
161.}  
162.}  
163.}).start();  
164.}  
165./**  
166.* 发送命令并接受响应  
167.* @param requestMsg  
168.* @return  
169.* @throws SocketTimeoutException  
170.* @throws IOException  
171.*/  
172.public String readReqMsg(String requestMsg) throws IOException {  
173.
if(requestMsg ==null) {  

174.return null;  
175.}  
176.if(!isNetworkConnect) {  
177.synchronized(this){  
178.try {  
179.this.wait(1000*5); //等待5秒,如果网络还没有恢复,抛出IO流异常  
180.if(!isNetworkConnect) {  
181.throw new IOException("网络连接中断!");  
182.}  
183.} catch (InterruptedException e) {  
184.log.error("发送线程中断",e);  
185.}  
186.}  
187.}  
188.
String msgNo = requestMsg.substring(8, 8 + 24);//读取流水号  

189.
outStream = socket.getOutputStream();  

190.outStream.write(requestMsg.getBytes());  
191.outStream.flush();  
192.
Condition msglock = lock.newCondition(); //消息锁  

193.//注册等待接收消息  
194.recMsgMap.put(msgNo, msglock);  
195.try {  
196.lock.lock();  
197.msglock.await(timeout,TimeUnit.MILLISECONDS);  
198.} catch (InterruptedException e) {  
199.log.error("发送线程中断",e);  
200.} finally {  
201.lock.unlock();  
202.}  
203.
Object respMsg = recMsgMap.remove(msgNo); //响应信息  

204.if(respMsg!=null &&(respMsg != msglock)) {  
205.//已经接收到消息,注销等待,成功返回消息  
206.return (String) respMsg;  
207.} else {  
208.log.error(msgNo+" 超时,未收到响应消息");  
209.throw new SocketTimeoutException(msgNo+" 超时,未收到响应消息");  
210.}  
211.}  
212.public void finalize() {  
213.if (socket != null) {  
214.try {  
215.socket.close();  
216.} catch (IOException e) {  
217.e.printStackTrace();  
218.}  
219.}  
220.}  
221.//消息接收线程  
222.private class ReceiveWorker implements Runnable {  
223.
String intStr= null;  

224.public void run() {  
225.while(!Thread.interrupted()){  
226.try {  
227.
byte[] headBytes = new byte[4];  

228.if(inStream.read(headBytes)==-1){  
229.log.warn("读到流未尾,对方已关闭流!");  
230.reConnectToCTCC();//读到流未尾,对方已关闭流  
231.return;  
232.}  
233.
byte[] tmp =new byte[4];  

234.
tmp = headBytes;  

235.
String tempStr = new String(tmp).trim();  

236.
if(tempStr==null || tempStr.equals("")) {  

237.log.error("received message is null");  
238.continue;  
239.}  
240.
intStr = new String(tmp);  

241.
int totalLength =Integer.parseInt(intStr);  

242.//----------------  
243.
byte[] msgBytes = new byte[totalLength-4];  

244.inStream.read(msgBytes);  
245.
String resultMsg = new String(headBytes)+ new
String(msgBytes);  

246.//抽出消息ID  
247.
String msgNo = resultMsg.substring(8, 8 + 24);  

248.
Condition msglock =(Condition) recMsgMap.get(msgNo);  

249.
if(msglock ==null) {  

250.log.warn(msgNo+"序号可能已被注销!响应消息丢弃");  
251.recMsgMap.remove(msgNo);  
252.continue;  
253.}  
254.recMsgMap.put(msgNo, resultMsg);  
255.try{  
256.lock.lock();  
257.msglock.signalAll();  
258.}finally {  
259.lock.unlock();  
260.}  
261.}catch(SocketException e){  
262.log.error("服务端关闭socket",e);  
263.reConnectToCTCC();  
264.} catch(IOException e) {  
265.log.error("接收线程读取响应数据时发生IO流异常",e);  
266.} catch(NumberFormatException e){  
267.log.error("收到没良心包,String转int异常,异常字符:"+intStr);  
268.}  
269.}  
270.}  
271.}  
272.}

你可能感兴趣的:(java,thread,.net,log4j,socket)