在Android开发中,基于Socket的通信必须是非阻塞式的,因此需要Reader和Writer异步分离,此外需要监听Socket网络状态、
监听接口
package com.io.sockets;
import java.io.IOException;
import java.net.Socket;
public interface SocketStatusListener
{
public static final int STATUS_OPEN = 0x01<<0;
public static final int STATUS_CLOSE = 0x01<<1;
public static final int STATUS_RESET = 0x01<<2;
public static final int STATUS_PIP_BROKEN = 0x01<<3;
public static final int STATUS_UNKOWN = 0x01<<4;
public void onSocketStatusChanged(Socket socket,int status,IOException e);
}
Handler读写处理控制
package com.io.sockets;
import java.io.IOException;
import java.net.Socket;
public class SocketHandler implements SocketStatusListener {
private Socket socket=null;
private ReaderTask reader;
private WriterTask writer;
public SocketHandler(Socket socket) throws IOException {
this.socket = socket;
this.socket.setTcpNoDelay(true);
reader = new ReaderTask(socket);
writer = new WriterTask(socket);
onSocketStatusChanged(socket, STATUS_OPEN, null);
}
/**
* sendMessage:(这里用一句话描述这个方法的作用). <br/>
* TODO(这里描述这个方法适用条件 – 可选).<br/>
*/
public void sendMessage(String msg) {
writer.send(msg);
}
public void listen(boolean isListen)
{
reader.startListener(this);
}
public void shutDown() {
if(!socket.isClosed() &&socket.isConnected())
{
try {
writer.finish();
reader.finish();
socket.close();
} catch (IOException e) {
e.printStackTrace();
onSocketStatusChanged(socket, STATUS_CLOSE, e);
}finally{
reader = null;
writer = null;
System.out.println("Socket连接已关闭!!");
}
}
}
@Override
public void onSocketStatusChanged(Socket socket,int status, IOException e) {
switch (status) {
case SocketStatusListener.STATUS_CLOSE:
case SocketStatusListener.STATUS_RESET:
case SocketStatusListener.STATUS_PIP_BROKEN:
shutDown();
break;
default:
break;
}
}
}
读取任务
package com.io.sockets;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.SocketException;
public class ReaderTask extends Thread{
private SocketStatusListener socketStatusListener;
private BufferedReader bufferedReader;
private Socket socket;
private boolean listening;
public ReaderTask(Socket socket) throws IOException
{
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
this.socket = socket;
}
/**
* finish:(这里用一句话描述这个方法的作用). <br/>
* TODO(这里描述这个方法适用条件 – 可选).<br/>
* @throws IOException
*
*/
public void finish() throws IOException
{
listening = false;
interrupt();
if(bufferedReader!=null && socket!=null)
{
if(socket.isInputShutdown())
{
socket.shutdownInput();
}
bufferedReader.close();
}
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public synchronized void run()
{
while (listening)
{
String readStr = null;
try {
while((readStr=bufferedReader.readLine())!=null)
{
System.err.println("[Server]:"+readStr);
}
} catch (IOException e) {
listening = false;
if(socketStatusListener!=null)
{
int status = parseSocketStatus(e);
socketStatusListener.onSocketStatusChanged(socket, status, e);
}
e.printStackTrace();
return;//终止线程继续运行,这里也可以使用continue
}
}
}
private int parseSocketStatus(IOException e)
{
if(SocketException.class.isInstance(e))
{
String msg = e.getLocalizedMessage().trim();
if("Connection reset".equalsIgnoreCase(msg))
{
return SocketStatusListener.STATUS_RESET;
}
else if("Socket is closed".equalsIgnoreCase(msg))
{
return SocketStatusListener.STATUS_CLOSE;
}
else if("Broken pipe".equalsIgnoreCase(msg))
{
return SocketStatusListener.STATUS_PIP_BROKEN;
}
}
return SocketStatusListener.STATUS_UNKOWN;
}
/**
* listen:(这里用一句话描述这个方法的作用). <br/>
* TODO(这里描述这个方法适用条件 – 可选).<br/>
*
*/
public void startListener(SocketStatusListener ssl) {
listening = true;
this.socketStatusListener = ssl;
start();
}
}
写入任务
package com.io.sockets;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
public class WriterTask extends Thread{
private BufferedWriter bufferedWriter;
private String msg = null;
private Socket socket = null;
public WriterTask(Socket socket) throws IOException {
this.bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
this.socket = socket;
}
/**
* finishTask:(这里用一句话描述这个方法的作用). <br/>
* TODO(这里描述这个方法适用条件 – 可选).<br/>
* @throws IOException
*
*/
public void finish() throws IOException {
if(bufferedWriter!=null && socket!=null)
{
if(!socket.isOutputShutdown())
{
socket.shutdownOutput();
}
bufferedWriter.close();
}
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public synchronized void run() {
try {
bufferedWriter.write(msg);
bufferedWriter.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public void send(String msg){
this.msg = msg;
new Thread(this).start();
}
}
Server端测试
public class TcpSocketServer {
public static void main(String[] args) {
List<SocketHandler> serverHandlers = new CopyOnWriteArrayList<SocketHandler>();
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(8090, 5);
while(true)
{
Socket clientSocket = serverSocket.accept();
if(clientSocket.isConnected())
{
SocketHandler serverHandler = new SocketHandler(clientSocket);
serverHandlers.add(serverHandler);
serverHandler.listen(true);
serverHandler.sendMessage("Host:"+serverSocket.getInetAddress().getHostAddress()+"\r\n");
/*while (true)
{
Scanner sc = new Scanner(System.in);
String next = sc.nextLine()+"\r\n";
for (SocketHandler scItem : serverHandlers) {
scItem.sendMessage(next);
}
}*/
}
}
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
for (SocketHandler serverHandler : serverHandlers)
{
serverHandler.shutDown();
}
serverHandlers.clear();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
客户端测试
public class TcpSocketClient {
public static void main(String[] args) {
SocketHandler clientHandler = null;
try {
Socket clientSocket = new Socket("localhost", 8090);
clientSocket.setKeepAlive(true);
clientSocket.setTcpNoDelay(true);
if(clientSocket.isConnected())
{
clientHandler = new SocketHandler(clientSocket);
clientHandler.listen(true);
while (true)
{
Scanner sc = new Scanner(System.in);
String next = sc.nextLine()+"\r\n";
if(!clientSocket.isClosed())
{
clientHandler.sendMessage(next);
}else{
break;
}
}
}
} catch (IOException e) {
e.printStackTrace();
}finally{
clientHandler.shutDown();
}
}
}