Socket的轻量级的实现

 最近在做一些Socket通讯的项目,用一些简单的Socket又不稳定,所以 利用这个机会自己封了一套Socket通讯的实现方法.,实现的过程非常简单.经过测试,使用起来还算稳定.换不多说 直接上代码.

// 首先是几个回调,用于Socket转态和数据的回调

public interface ConnectListener {
	void receive(byte[] data);
	void disconnect();
	void connectOk();
	void connectFailed(Exception e);
}

//设置Socket的一些配置信息

public class SessionConfig {

	/** address */
	private String ip;

	/** port */
	private int port;

	/** connect timeout, unit seconds */
	private int timeOut;

	/** connect Interval, unit seconds */
	private int interval;

	/** get address */
	public String getIp() {
		return ip;
	}

	/** get port */
	public int getPort() {
		return port;
	}

	/** get connect timeout */
	public int getTimeOut() {
		return timeOut;
	}

	/** get connect Interval */
	public int getInterval() {
		return interval;
	}

	public static class Builder {
		/** address */
		private String ip;

		/** port */
		private int port;

		/** connect timeout, unit seconds */
		private int timeOut;

		/** connect Interval, unit seconds */
		private int interval;

		/** set address */
		public Builder setIp(String ip) {
			this.ip = ip;
			return this;
		}

		/** set port */
		public Builder setPort(int port) {
			this.port = port;
			return this;
		}

		/** set connect timeout */
		public Builder setTimeOut(int timeOut) {
			this.timeOut = timeOut;
			return this;
		}

		/** set connect Interval */
		public Builder setInterval(int interval) {
			this.interval = interval;
			return this;
		}

		/** build a SessionConfig */
		public SessionConfig build() {
			SessionConfig config = new SessionConfig();
			config.ip       = this.ip;
			config.port     = this.port;
			config.timeOut  = this.timeOut;
			config.interval = this.interval;
			return config;
		}
	}

	@Override
	public String toString() {
		return "SessionConfig [ip=" + ip + ", port=" + port + ", timeOut="
				+ timeOut + ", interval=" + interval + "]";
	}

//socket的连接,读取数据的线程,代码非常简单,也有一些注释 看一下就会明白


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;


abstract class SocketTransceiver implements Runnable {
	private static final String TAG = "SocketTransceiver";
	private boolean runFlag;
	private Socket socket;
	private InetAddress addr;
	private InputStream inputStream;
	private OutputStream outputStream;

	SocketTransceiver(Socket socket) {
		this.socket = socket;
		this.addr   = socket.getInetAddress();
	}

	InetAddress getInetAddress() {
		return addr;
	}

	void start() {
		
		runFlag = true;
		try {
			inputStream  = this.socket.getInputStream();
			outputStream = this.socket.getOutputStream();
			
		} catch (IOException e) {
			runFlag = false;
		}
		new Thread(this, TAG).start();
	}

	void stop() {
		
		runFlag = false;
		try {
			socket.shutdownInput();
			inputStream.close();
			
			outputStream.close();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void run() {
		while (runFlag) {
			try {
				if (inputStream == null)    return;
				
				byte[] buffer = new byte[inputStream.available()];
				int len       = inputStream.read(buffer);
				
				if(len > 5) {
					receive(addr, buffer);
					
//					if (msgCheck(buffer)) {
//						bytesOperation(buffer, len);
//					} 
				}
				
				Thread.sleep(20);
			} catch (Exception e) {
				runFlag = false;
				disconnect(addr);
			}
		}
	}

	/**
	 * 处理粘包、半包、断包的情况
	 * @param buffer   read buffer
	 * @param len      data length
	 */
	/*private void bytesOperation(byte[] buffer, int len) {
			byte[] data = new byte[len];
			System.arraycopy(buffer, 0, data, 0, len);
			apped2ByteBuffer(data);
		}

	private ByteBuffer buf = ByteBuffer.allocate(1024);
	private void apped2ByteBuffer(byte[] data) {
		for (byte b : data) {
			if (b == 0x7E) {
				// mark = position
				buf.mark();

				if (mark(buf) == 1 && buf.get(0) == 0x7E)  continue;

				// position++
				buf.put(b);
				// mark = position
				buf.mark();

				if (mark(buf) > 1) {
					buf.flip();
					byte[] out = new byte[buf.limit() - buf.position()];
					buf.get(out);
					if (out[0] == 0x7E && out[out.length - 1] == 0x7E) {
						receive(addr, out);
						// position = 0 ; limit = capacity ; mark = -1
						buf.clear();
					}
				}
				continue;
			} else {
				if (buf.get(0) == 0x7E)   buf.put(b);
			}
		}
	}
	
	public static boolean msgCheck(byte[] pBuf) {
		if (pBuf[0] != 0x7E || pBuf[pBuf.length - 1] != 0x7E) return false;
		int count = 0;

		for (int i = 1; i < pBuf.length - 1; i++) {
			if (i == pBuf.length - 1 - 1)   break;
			
			if ((pBuf[i] == 0x7D && (pBuf[i] + pBuf[i + 1] == 0x7F)) || (pBuf[i] == 0x7D && (pBuf[i] + pBuf[i + 1] == 0x7E))) {
				count++;
				continue;
			}
		}

		int MessageLength = pBuf.length - count;
		byte[] bytes = new byte[MessageLength];
		int MessageIndex = 0;

		for (int i = 0; i < bytes.length; i++) {
			if (pBuf[MessageIndex] == 0x7D && pBuf[MessageIndex] + pBuf[MessageIndex + 1] == 0x7F) {
				bytes[i] = 0x7E;
				MessageIndex += 2;
				continue;
			}

			if (pBuf[MessageIndex] == 0x7D && pBuf[MessageIndex] + pBuf[MessageIndex + 1] == 0x7E) {
				bytes[i] = pBuf[MessageIndex];
				MessageIndex += 2;
				continue;
			}
			bytes[i] = pBuf[MessageIndex];
			MessageIndex++;
		}
		
		int CheckCode = 0;
		for (int i = 1; i < bytes.length - 2; i++)   CheckCode ^= bytes[i];

		if (CheckCode == bytes[bytes.length - 2]) {
//			int command = Byte2Int(new byte[] { bytes[1], bytes[2] });
//			try {
//				MessageParse(command, bytes);  
//			} catch (Exception e) {
//				e.printStackTrace();
//			}
			return true;
		}
		return false;
	}

	private int mark(ByteBuffer buff) {
		try {
			Field field = buff.getClass().getSuperclass().getSuperclass().getDeclaredField("mark");
			field.setAccessible(true);
			return field.getInt(buff);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return -100;
		
	} */

	/**
	 * 发送byte[]数据
	 * @param data
	 *            需要发送的内容
	 */
	void send(byte[] data) throws IOException {
		if (outputStream == null)  return;
		
		if (data != null && data.length > 0) {
			outputStream.write(data);
			outputStream.flush();
			
		}
	}

	/**
	 * 接收到数据
	 * 注意:此回调是在新线程中执行的
	 * @param addr
	 *            连接到的Socket地址
	 * @param s
	 *            收到的字符串
	 */
	abstract void receive(InetAddress addr, byte[] data);

	/**
	 * 连接断开
	 * <p>
	 * 注意:此回调是在新线程中执行的
	 * 
	 * @param addr
	 *            连接到的Socket地址
	 */
	abstract void disconnect(InetAddress addr);
}

//Socket的连接类,器主要作用是连接上后回调转态出去, 


import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;


abstract class SocketConnector implements Runnable {
	private static final String TAG = "SocketConnector";
	private int port;
	private String hostIP;
	private volatile boolean connect = false;
	private Socket socket;
	private SocketTransceiver transceiver;
	private SocketAddress mSocketAddress;

	void connect(SessionConfig config) {
		this.hostIP   = config.getIp();
		this.port     = config.getPort();
		
		new Thread(this, TAG).start();
	}

	private void connectSocket() {
		if (mSocketAddress == null) {
			mSocketAddress = new InetSocketAddress(hostIP, port);
		} 

		if (transceiver == null) {
			transceiver = new SocketTransceiver(socket) {
				@Override
				public void receive(InetAddress addr, byte[] data) {
					SocketConnector.this.receive(this, data);
				}

				@Override
				public void disconnect(InetAddress addr) {
					connect = false;
					SocketConnector.this.disconnect(this);
				}
			};
		}
	}
	
	@Override
	public void run() {
		RmtLog.d(JSATLApp.TAG, " run() AAA ");
		if (socket == null) {
			
			try {
				
				socket = new Socket(hostIP, port);
				
				
				if (socket.isConnected()) {
					
					
					connectSocket();

					transceiver.start();
					
					connect = true;
					
					connectOk(transceiver);
					
				} 
			} catch (IOException e) {
				connect = false;
				
				Log.d(TAG, "---BBB-----:"+ e.getMessage());
				
				connectFailed(e);
			}
		} 
	}

	void disconnect() {
		
		RmtLog.d(JSATLApp.TAG, " SocketConnector disconnect() ");
		
		try {
			if (transceiver != null) {
				transceiver.stop();
				
				Log.d(App.TAG, " Receive stop() ");
			}
			
			transceiver = null;
			
			if (socket != null) {
				socket.close();
				
				Log.d(App.TAG, " Socket close() ");
			}
			
			socket = null;
			
			connect = false;
			
			mSocketAddress = null;
			
			Log.d(App.TAG, " Close All " + connect);
			
		} catch (IOException e) {
			e.printStackTrace();
			
			Log.d(App.TAG, " Close All IOException " + e.getMessage());
		}
	}

	/**
	 * 判断是否连接
	 * @return 当前处于连接状态,则返回true
	 */
	boolean isConnected() {
		return connect;
	}

	/**
	 * 获取Socket收发器
	 */
	SocketTransceiver getTransceiver() {
		return isConnected() ? transceiver : null;
	}

	/**
	 * 连接建立
	 */
	abstract void connectOk(SocketTransceiver transceiver);

	/**
	 * 连接建立失败
	 */
	abstract void connectFailed(Exception e);

	/**
	 * 接收到数据
	 * 注意:此回调是在新线程中执行的
	 */
	abstract void receive(SocketTransceiver transceiver, byte[] data);

	/**
	 * 连接断开
	 * 注意:此回调是在新线程中执行的
	 * @param transceiver  SocketTransceiver对象
	 */
	abstract void disconnect(SocketTransceiver transceiver);
}

//外部调用的类.通过该类即可实现 


import java.io.IOException;


public class ConnectManager {
	private static ConnectManager instance;
	private SocketConnector connector;
	private SocketTransceiver transceiver;
	private ConnectListener listener;

	public static ConnectManager asInstance() {
		if (instance == null) {
			synchronized (ConnectManager.class) {
				if (instance == null) {
					instance = new ConnectManager();
				}
			}
		}
		return instance;
	}

	private ConnectManager() {
		connector = new SocketConnector() {
			@Override
			void receive(SocketTransceiver transceiver, byte[] data) {
				if (listener != null)   listener.receive(data);
			}

			@Override
			void disconnect(SocketTransceiver transceiver) {
				if (listener != null)   listener.disconnect();
			}

			@Override
			void connectOk(SocketTransceiver transceiver) {
				ConnectManager.this.transceiver = transceiver;
				if (listener != null)  listener.connectOk();
			}

			@Override
			void connectFailed(Exception e) {
				if (listener != null)  listener.connectFailed(e);
			}
		};
	}

	public void registerConnectListener(ConnectListener listener) {
		this.listener = listener;
	}

	public void unregisterConnectListener() {
		this.listener = null;
	}

	public void connect(SessionConfig config) {
		
		if (connector == null)  return;
		
		connector.connect(config);
	}

	public boolean isConnect() {
		if (connector == null)   return false;
		
		return connector.isConnected();
	}

	public void write(byte[] data) {
		if (data == null || data.length == 0)    return;
		if (transceiver == null)                 return;
		
		try {
			if(connector.isConnected()) { // add
				transceiver.send(data);
			}
			
		} catch (IOException e) {
			e.printStackTrace();
			connector.connectFailed(e);
		}
	}

	public void disconnect() {
		if (connector == null)   return;
		
		Log.d(App.TAG, " ConnectManager disconnect() ");
		
		connector.disconnect();
	}

	public void release() {
		unregisterConnectListener();
		
		if (connector != null) {
			connector.disconnect();
			connector = null;
			
			Log.d(LApp.TAG, " ConnectManager release) ");
		}
		
		transceiver = null;
		instance    = null;
		
		Log.d(App.TAG, " Release All ");
	}
}

调用方法如下 :

ConnectManager   mConnector = ConnectManager.asInstance();  // 单列初始化

mConnector.connect(config);   // 开始连接


 mConnector.registerConnectListener(listener);  // 设置一个监听

private ConnectListener listener = new ConnectListener() {
        @Override
        public void receive(byte[] s) {
          // do Something   读取的数据接收
        }

        @Override
        public void disconnect() {
       // do Something   连接断开
        }

        @Override
        public void connectOk() {
         // do Something   连接OK 
        }

        @Override
        public void connectFailed(Exception e) { 
          // do Something  连接出错
        }
    };

到这里就结束了,是不是很简单呢,.赶紧下载使用吧

Code下载

猜你喜欢

转载自blog.csdn.net/u011694328/article/details/106287317