/**
* 客户端
*/
public final class SubsetSocket {
private static SubsetSocket instance;
private StringBuffer stringBuffer = new StringBuffer();
private SubsetSocket() {
}
public static SubsetSocket getInstance() {
if (instance == null) {
synchronized (SubsetSocket.class) {
if (instance == null) {
instance = new SubsetSocket();
instance.connect();
}
}
}
return instance;
}
private Vector<String> queue = new Vector<>();
private ExecutorService singleSendDataThread = Executors.newSingleThreadExecutor();
private ExecutorService singleConnectThread = Executors.newSingleThreadExecutor();
private boolean isConnect = false;
private boolean sendRunning = false;
private OutputStream out;
private InputStream in;
private Socket socket = null;
private Runnable sendRunnable = new Runnable() {
public void run() {
sendRunning = true;
while (queue.size() > 0) {
if (out != null) {
synchronized (this) {
try {
String command = DATA_HEAD+queue.get(0);
McLog.w(TAG, "write:" + command);
out.write(command.getBytes());
out.flush();
queue.remove(0);
} catch (Exception e) {
queue.remove(0);
e.printStackTrace();
}
}
}
}
sendRunning = false;
}
};
private Runnable connect = new Runnable() {
@Override
public void run() {
try {
//
socket = new Socket(ip, port, null, 0);
socket.setSoTimeout(10000);
socket.setKeepAlive(true);
socket.setTcpNoDelay(true);
out = socket.getOutputStream();
in = socket.getInputStream();
isConnect = true;
// login();
while (socket != null && !socket.isClosed()) {
try {
byte[] rec = new byte[1024 * 10];
McLog.w(TAG, "wait read.");
int read = in.read(rec);
if (read < 0 )return;
String newMsg = new String(rec, 0, read);
if (!TextUtils.isEmpty(newMsg)) {
McLog.w(TAG, "read content: " + newMsg);
if (newMsg.startsWith(DATA_HEAD)
&& newMsg.endsWith("}")) {
newMsg = newMsg.substring(DATA_HEAD.length());
receiveData(newMsg);
stringBuffer.setLength(0);
}else {
stringBuffer.append(newMsg);
parseData();
}
}
} catch (SocketTimeoutException e) {
//超时异常不需要处理
} catch (Exception e2) {
e2.printStackTrace();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
close();
}
}
} catch (Exception e) {
e.printStackTrace();
McLog.w(TAG, e.getMessage());
}
}
};
/**
* 解包,可能产生多段结果,通过pretreatment进行数据上报
*/
private void parseData() {
int indexOf = stringBuffer.indexOf(DATA_HEAD);
Log.d(TAG, "parseData: " +stringBuffer.toString());
try {
if (indexOf == 0) {
//去除数据头部 取内容体
String body = stringBuffer.substring(DATA_HEAD.length());
//第二段索引
int index = body.indexOf(DATA_HEAD);
if (index == -1){
if (!body.endsWith("}"))return; //没有结束
receiveData(body);
Log.d(TAG, "recvResultToGateway: 一个" + body);
stringBuffer.setLength(0);//清空数据
}else {
//截取第一个结果
String substring = stringBuffer.substring(DATA_HEAD.length(), index+DATA_HEAD.length());
receiveData(substring);
Log.d(TAG, "recvResultToGateway: 多个" + substring);
stringBuffer.delete(0,index+DATA_HEAD.length());
parseData();
}
} else {
if (indexOf > 0) {
stringBuffer.delete(0, indexOf);
parseData();
}
}
} catch (Exception e) {
McLog.e(TAG, "parseData error:" + e.getMessage());
e.printStackTrace();
}
}
private void connect() {
if (!isConnect) {
singleConnectThread.execute(connect);
}
}
public void sendMsg(String command) {
synchronized (SubsetSocket.class) {
if (command != null) {
queue.add(command);
}
connect();
if (!sendRunning) {
singleSendDataThread.execute(sendRunnable);
}
}
}
public void close() {
isConnect = false;
sendRunning = false;
if (socket != null) {
try {
out.close();
in.close();
socket.close();
socket = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* socket服务端
*/
public class MasterDeviceSocketServer implements Runnable {
public static final int PORT = 6551;
public static final String DATA_HEAD = "master_head";
private static final int SERVER_MAX_CONNECTIONS = 10;
private static List<Callback> clientList = new ArrayList<>();
private int mPort;
private ServerSocket mServer;
private ExecutorService mThreadPool;
private Thread mThread;
private StringBuffer stringBuffer = new StringBuffer();
public MasterDeviceSocketServer(int port) {
if (port == 0) {
port = PORT;
}
this.mPort = port;
}
public static synchronized void offer(String data) {
McLog.d(TAG, "offer data:" + data);
data = DATA_HEAD + data;
for (Callback callback : clientList) {
McDispatcher dispatcher = (McDispatcher) callback;
dispatcher.sendData(data);
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public boolean start() {
if (mThread != null) {
return false;
}
try {
mServer = new ServerSocket(mPort);
mServer.setReuseAddress(true);
mThreadPool = Executors.newFixedThreadPool(SERVER_MAX_CONNECTIONS);
mThread = new Thread(this, "Remote Server [port=" + mPort + "]");
mThread.start();
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
public boolean stop() {
if (mThread != null) {
McLog.w(TAG, "---stop---");
mThread.interrupt();
if (mThreadPool != null) {
try {
mThreadPool.shutdownNow();
} catch (SecurityException e) {
McLog.w(TAG, "Could not stop all view server threads");
}
}
mThreadPool = null;
mThread = null;
try {
mServer.close();
mServer = null;
return true;
} catch (IOException e) {
McLog.w(TAG, "Could not close the view server");
}
}
return false;
}
public boolean isRunning() {
return mThread != null && mThread.isAlive();
}
@Override
public void run() {
while (Thread.currentThread() == mThread) {
try {
McLog.w(TAG, "---run start");
if (mServer != null) {
Socket socket = mServer.accept();
McLog.w(TAG, "socketClient:" + socket);
//TODO 需要发送Login来建全
String ip = socket.getInetAddress().getHostAddress();
McDispatcher dispatcher = new McDispatcher(socket);
dispatcher.setIp(ip);
if (!clientList.contains(dispatcher)) {
clientList.add(dispatcher);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public interface Callback {
void sendData(String data);
}
class McDispatcher implements Callback {
private final ExecutorService readThreadPool = Executors.newCachedThreadPool();
private final ExecutorService writeThreadPool = Executors.newCachedThreadPool();
private Socket mSocket;
private InputStream mInputStream;
private OutputStream mOutputStream;
private Future mReadFuture;
private Future mWriteFuture;
private ByteBuffer mRemainingBuf;
private String remoteAddress;
private String mIp, mName;
private LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>();
public McDispatcher(Socket socket) {
this.mSocket = socket;
try {
this.mInputStream = socket.getInputStream();
this.mOutputStream = socket.getOutputStream();
this.remoteAddress = mSocket.getInetAddress().getHostAddress();
mReadFuture = readThreadPool.submit(new Reader());
mWriteFuture = writeThreadPool.submit(new Writer());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void sendData(String data) {
try {
queue.put(data);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public String getName() {
return mName;
}
public void setName(String name) {
this.mName = name;
}
public String getIp() {
return mIp;
}
public void setIp(String ip) {
this.mIp = ip;
}
private class Writer implements Runnable {
private final String TAG = "MasterDeviceSocketServer.ClientWriter";
@Override
public void run() {
while (!mSocket.isClosed()) {
String data = null;//McMessageQueue.getInstance().take();
synchronized (this) {
try {
data = queue.take();
Thread.sleep(100);
McLog.w(TAG, "---take()---" + data);
if (!TextUtils.isEmpty(data)) {
mOutputStream.write(data.getBytes());
mOutputStream.flush();
McLog.w(TAG, "write address---:" + remoteAddress + " content:" + data +
"" + " " + "thread:" + Thread.currentThread().getName());
}
} catch (Exception e) {
e.printStackTrace();
McLog.e(TAG, "Error msg:" + e.getMessage(), e);
}
}
McLog.w(TAG, "---stop---");
}
}
}
private class Reader implements Runnable {
private final String TAG = "MasterDeviceSocketServer.ClientReader";
@Override
public void run() {
while (!mSocket.isClosed()) {
try {
McLog.w(TAG, "---wait read---:" + remoteAddress + " thread:" + Thread
.currentThread().getName());
byte[] buf = new byte[4096];
int length = mInputStream.read(buf);
if (length < 0) return;//
String reqCommand = new String(buf, 0, length);
McLog.w(TAG, "---read---:" + remoteAddress + " content:" + reqCommand);
if (reqCommand.startsWith(MasterDeviceSocketServer.DATA_HEAD)
&& reqCommand.endsWith("}")) {
reqCommand = reqCommand.substring(MasterDeviceSocketServer.DATA_HEAD.length());
receiveData(reqCommand);
stringBuffer.setLength(0);
} else {
stringBuffer.append(reqCommand);
parseData();
}
} catch (Exception e) {
//e.printStackTrace();
McLog.e(TAG, "error:" + e.getMessage(), e);
}
}
McLog.w(TAG, "reader end------");
}
}
}
/**
* 解包,可能产生多段结果,通过pretreatment进行数据上报
*/
private void parseData() {
int indexOf = stringBuffer.indexOf(MasterDeviceSocketServer.DATA_HEAD);
// Log.d(TAG, "parseData: " +stringBuffer.toString());
try {
if (indexOf == 0) {
//去除数据头部 取内容体
String body = stringBuffer.substring(MasterDeviceSocketServer.DATA_HEAD.length());
//第二段索引
int index = body.indexOf(MasterDeviceSocketServer.DATA_HEAD);
if (index == -1) {
if (!body.endsWith("}")) return; //没有结束
receiveData(body);
Log.d(TAG, "recvResultToGateway: 一个" + body);
stringBuffer.setLength(0);//清空数据
} else {
//截取第一个结果
String substring = stringBuffer.substring(MasterDeviceSocketServer.DATA_HEAD.length(), index + DATA_HEAD.length());
receiveData(substring);
Log.d(TAG, "recvResultToGateway: 多个" + substring);
stringBuffer.delete(0, index + DATA_HEAD.length());
parseData();
}
} else {
if (indexOf > 0) {
stringBuffer.delete(0, indexOf);
parseData();
}
}
} catch (Exception e) {
McLog.e(TAG, "parseData error:" + e.getMessage());
e.printStackTrace();
}
}
}