socket笔记

这次是在云端用java写一个serversocket来监听客户端socket的连接请求。

总体的结构就是启动一个监听线程,如果监听到了客户端的连接请求,就另外启动一个子线程去负责和此客户端的交互,直至客户端发完数据,主动关闭socket,此时服务端的子线程socket也就关闭了。代码如下:

package com.example.socket;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;


public class SSocket {
	public static final String TAG = "SSocket";
	private StringBuffer debug_buffer = new StringBuffer();
	public static final boolean ISDEBUG = true;
	private ServerSocket serverSocket = null;
	private boolean isStop = false;
	private static final int BUFFER_LENGTH = 4096;

	private DataOperator dataOperator = null;
	public SSocket(int port) {
		//启动监听线程
		try {
			serverSocket = new ServerSocket(port);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//实例化数据处理类
		dataOperator = new DataOperator();
		//启动监听线程
		Config.getExecutor().submit(new ListenRunnable());
	}
	
	public void closeSocket() {
		if(serverSocket!=null) {
			try {
				serverSocket.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			serverSocket=null;
		}
		isStop = true;
	}
	
	public class ListenRunnable implements Runnable {

		@Override
		public void run() {
			// TODO Auto-generated method stub
			while(!isStop) {
				try {
					//监听client的连接请求
					Socket client = serverSocket.accept();
					client.setSoTimeout(6000);
					//监听到了请求之后,另起线程与其交互
					Config.getExecutor().submit(new ExcecuteRunnable(client));
					
				} catch (IOException e) {
					try {
						Thread.sleep(400);
					} catch (InterruptedException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
				}
			}
			System.out.println("exit Listen runnable");
		}
		
	}
	
	public class ExcecuteRunnable implements Runnable {

		Socket socket = null;
		InputStream ins = null;
		OutputStream ous = null;
		byte[] buffer = null;
		int size = 0;
		int start = 0;
		int offsize = 0;
		public ExcecuteRunnable(Socket socket) {
			this.socket = socket;
			try {
				ins = socket.getInputStream();
				ous = socket.getOutputStream();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			//每一个交互线程启动一个接收数据的buffer
			buffer = new byte[BUFFER_LENGTH];
		}
		
		@Override
		public void run() {
			// TODO Auto-generated method stub
			while(!isStop) {
				
				if(ins != null && buffer != null) {
					try {
						size = ins.read(buffer, offsize, BUFFER_LENGTH-offsize);
						if(size > 0) {
							start = offsize;
							//把offsize移位到数据的最后,即0x03的后一位,也就是下次接收数据的开始处
							offsize = (offsize + size)%BUFFER_LENGTH;
							if(ISDEBUG) {
								debug_buffer.append("offsize = "+offsize+"\nbuffer = "+Funs.bytesToHexStr(buffer, 0, offsize));
//								Log.i(TAG,debug_buffer.toString());
								System.out.println(debug_buffer.toString());
								debug_buffer.setLength(0);
							}
							//判断接收到的数据的末位是否为03,如果是的话就表示接收的是一个完整数据,02开始03结束
							if(buffer[(offsize - 1+BUFFER_LENGTH)%BUFFER_LENGTH] == (byte)0x03) {
								byte[] sendData = dataOperator.oprData(buffer,start,offsize,BUFFER_LENGTH);
								ous.write(sendData);
							} else {
								//数据还没有完整接收,因为是在buffer的最后了,需要从buffer的开始接收数据的后半部分
								continue;
							}
						} else if(size == -1) {
							//client close socket,所以此交互线程也要跳出while并结束了
							break;
						}
					} catch(SocketTimeoutException ste) {
						System.err.println("SocketTimeoutException");
						continue;
					} catch (IOException e) {
						System.err.println("IOException");
						e.printStackTrace();
						break;
					} 
				} else {
					System.err.println("buffer = null");
					break;
				}
			}//end while
			
			System.out.println("exit socket runnable");
			try {
				if(socket != null) {
					socket.close();
					socket = null;
				}
				if(ins != null) {
					ins.close();
					ins = null;
				}
				if(ous != null) {
					ous.close();
					ous = null;
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}//end run
		
	}
	
}

数据处理如下:


public synchronized byte[] oprData(byte[] buffer, int start, int offsize, int bufferLength) {

		byte[] sendData = null;
		int head = start;
		int tail = offsize;
		int i = head;
		while(i !=  tail) {
			if(buffer[i] == (byte)0x02) {
				head = i;
			} else if(buffer[i] == (byte)0x03) {
				int len = (i-head+bufferLength+1)%bufferLength;
				if(len > 8) {
					if(check(buffer,head,(i+1)%bufferLength,bufferLength)) {
						String jsonString = null;
						byte[] data = new byte[len-8];
						if(i > head) {//03在02后面
							System.arraycopy(buffer, head+5, data, 0, len-8);
						} else {//03再02之前
							System.arraycopy(buffer, (head+5)%bufferLength, data, 0, bufferLength-(head+5)%bufferLength);
							System.arraycopy(buffer, 0, data, bufferLength - (head+5)%bufferLength, len-8-bufferLength+(head+5)%bufferLength);
						}
						
						String hexString = new String(data,0,data.length);
						byte[] hexByte = Funs.HexStringToBytes(hexString);
						byte[] mData = EncDec.dec_3Des(hexByte, Config.pKey);
						jsonString = new String(mData);
						sendData = getServerData(jsonString);
					} else {
						System.err.println("data check error");
					}
						
				
				}
				
			}
			
			i = (i+1)%bufferLength;
		}
		
		return sendData;
	}
getServerData就是从云端得到client想要得到的数据并传给client。

此前也这么做过,在Android  的service中new一个长度足够的buffer,然后把这个buffer作为ssocket的构造参数传递给ssocket,ssocket从客户端接受的数据就存往此buffer中,然后在上面ssocket中
dataOperator.oprData(buffer,start,offsize,BUFFER_LENGTH);

替换为通过handler给service发消息,并把offsize传递过去

if(handler != null) {
handler.obtainMessage(0x123, (Integer)offsize).sendToTarget();
}

service收到此消息,就会开始进行数据处理。当然,在service中也会有两个int的变量,标记buffer上一次存到哪里了,这一次从哪里开始处理,因为传过来的只是buffer的结束位置,并没有开始位置。

data_end = obj2Integer(msg.obj);
oprData();
data_begin = data_end;

你可能感兴趣的:(socket笔记)