在Android开发中,基于Socket的通信必须是非阻塞式的,因此需要Reader和Writer异步分离,此外需要监听Socket网络状态、
监听接口
packagecom.io.sockets;
importjava.io.IOException;
.Socket;
publicinterfaceSocketStatusListener
{
publicstaticfinalintSTATUS_OPEN=0x01<<0;
publicstaticfinalintSTATUS_CLOSE=0x01<<1;
publicstaticfinalintSTATUS_RESET=0x01<<2;
publicstaticfinalintSTATUS_PIP_BROKEN=0x01<<3;
publicstaticfinalintSTATUS_UNKOWN=0x01<<4;
publicvoidonSocketStatusChanged(Socketsocket,intstatus,IOExceptione);
}
Handler读写处理控制
packagecom.io.sockets;
importjava.io.IOException;
.Socket;
publicclassSocketHandlerimplementsSocketStatusListener{
privateSocketsocket=null;
privateReaderTaskreader;
privateWriterTaskwriter;
publicSocketHandler(Socketsocket)throwsIOException{
this.socket=socket;
this.socket.setTcpNoDelay(true);
reader=newReaderTask(socket);
writer=newWriterTask(socket);
onSocketStatusChanged(socket,STATUS_OPEN,null);
}
/**
*sendMessage:(这里用一句话描述这个方法的作用).
*TODO(这里描述这个方法适用条件–可选).
*/
publicvoidsendMessage(Stringmsg){
writer.send(msg);
}
publicvoidlisten(booleanisListen)
{
reader.startListener(this);
}
publicvoidshutDown(){
if(!socket.isClosed()&&socket.isConnected())
{
try{
writer.finish();
reader.finish();
socket.close();
}catch(IOExceptione){
e.printStackTrace();
onSocketStatusChanged(socket,STATUS_CLOSE,e);
}finally{
reader=null;
writer=null;
System.out.println("Socket连接已关闭!!");
}
}
}
@Override
publicvoidonSocketStatusChanged(Socketsocket,intstatus,IOExceptione){
switch(status){
caseSocketStatusListener.STATUS_CLOSE:
caseSocketStatusListener.STATUS_RESET:
caseSocketStatusListener.STATUS_PIP_BROKEN:
shutDown();
break;
default:
break;
}
}
}
读取任务
packagecom.io.sockets;
importjava.io.BufferedReader;
importjava.io.IOException;
importjava.io.InputStreamReader;
.Socket;
.SocketException;
publicclassReaderTaskextendsThread{
privateSocketStatusListenersocketStatusListener;
privateBufferedReaderbufferedReader;
privateSocketsocket;
privatebooleanlistening;
publicReaderTask(Socketsocket)throwsIOException
{
bufferedReader=newBufferedReader(newInputStreamReader(socket.getInputStream()));
this.socket=socket;
}
/**
*finish:(这里用一句话描述这个方法的作用).
*TODO(这里描述这个方法适用条件–可选).
*@throwsIOException
*
*/
publicvoidfinish()throwsIOException
{
listening=false;
interrupt();
if(bufferedReader!=null&&socket!=null)
{
if(socket.isInputShutdown())
{
socket.shutdownInput();
}
bufferedReader.close();
}
}
/*(non-Javadoc)
*@seejava.lang.Runnable#run()
*/
@Override
publicsynchronizedvoidrun()
{
while(listening)
{
StringreadStr=null;
try{
while((readStr=bufferedReader.readLine())!=null)
{
System.err.println("[Server]:"+readStr);
}
}catch(IOExceptione){
listening=false;
if(socketStatusListener!=null)
{
intstatus=parseSocketStatus(e);
socketStatusListener.onSocketStatusChanged(socket,status,e);
}
e.printStackTrace();
return;//终止线程继续运行,这里也可以使用continue
}
}
}
privateintparseSocketStatus(IOExceptione)
{
if(SocketException.class.isInstance(e))
{
Stringmsg=e.getLocalizedMessage().trim();
if("Connectionreset".equalsIgnoreCase(msg))
{
returnSocketStatusListener.STATUS_RESET;
}
elseif("Socketisclosed".equalsIgnoreCase(msg))
{
returnSocketStatusListener.STATUS_CLOSE;
}
elseif("Brokenpipe".equalsIgnoreCase(msg))
{
returnSocketStatusListener.STATUS_PIP_BROKEN;
}
}
returnSocketStatusListener.STATUS_UNKOWN;
}
/**
*listen:(这里用一句话描述这个方法的作用).
*TODO(这里描述这个方法适用条件–可选).
*
*/
publicvoidstartListener(SocketStatusListenerssl){
listening=true;
this.socketStatusListener=ssl;
start();
}
}
写入任务
packagecom.io.sockets;
importjava.io.BufferedWriter;
importjava.io.IOException;
importjava.io.OutputStreamWriter;
.Socket;
publicclassWriterTaskextendsThread{
privateBufferedWriterbufferedWriter;
privateStringmsg=null;
privateSocketsocket=null;
publicWriterTask(Socketsocket)throwsIOException{
this.bufferedWriter=newBufferedWriter(newOutputStreamWriter(socket.getOutputStream()));
this.socket=socket;
}
/**
*finishTask:(这里用一句话描述这个方法的作用).
*TODO(这里描述这个方法适用条件–可选).
*@throwsIOException
*
*/
publicvoidfinish()throwsIOException{
if(bufferedWriter!=null&&socket!=null)
{
if(!socket.isOutputShutdown())
{
socket.shutdownOutput();
}
bufferedWriter.close();
}
}
/*(non-Javadoc)
*@seejava.lang.Runnable#run()
*/
@Override
publicsynchronizedvoidrun(){
try{
bufferedWriter.write(msg);
bufferedWriter.flush();
}catch(IOExceptione){
e.printStackTrace();
}
}
publicvoidsend(Stringmsg){
this.msg=msg;
newThread(this).start();
}
}
Server端测试
publicclassTcpSocketServer{
publicstaticvoidmain(String[]args){
ListserverHandlers=newCopyOnWriteArrayList();
ServerSocketserverSocket=null;
try{
serverSocket=newServerSocket(8090,5);
while(true)
{
SocketclientSocket=serverSocket.accept();
if(clientSocket.isConnected())
{
SocketHandlerserverHandler=newSocketHandler(clientSocket);
serverHandlers.add(serverHandler);
serverHandler.listen(true);
serverHandler.sendMessage("Host:"+serverSocket.getInetAddress().getHostAddress()+"\r\n");
/*while(true)
{
Scannersc=newScanner(System.in);
Stringnext=sc.nextLine()+"\r\n";
for(SocketHandlerscItem:serverHandlers){
scItem.sendMessage(next);
}
}*/
}
}
}catch(IOExceptione){
e.printStackTrace();
}finally{
try{
for(SocketHandlerserverHandler:serverHandlers)
{
serverHandler.shutDown();
}
serverHandlers.clear();
serverSocket.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
}
客户端测试
publicclassTcpSocketClient{
publicstaticvoidmain(String[]args){
SocketHandlerclientHandler=null;
try{
SocketclientSocket=newSocket("localhost",8090);
clientSocket.setKeepAlive(true);
clientSocket.setTcpNoDelay(true);
if(clientSocket.isConnected())
{
clientHandler=newSocketHandler(clientSocket);
clientHandler.listen(true);
while(true)
{
Scannersc=newScanner(System.in);
Stringnext=sc.nextLine()+"\r\n";
if(!clientSocket.isClosed())
{
clientHandler.sendMessage(next);
}else{
break;
}
}
}
}catch(IOExceptione){
e.printStackTrace();
}finally{
clientHandler.shutDown();
}
}
}
原文:/ososchina/blog/509052