【转载】用线程解决Socket的getInputStream阻塞
| 分类: 应用系统、编程方面 |
1.背景:
在Socket通信中,当我们希望传输对象时,往往会用到输入/输出对象流。
ObjectInputStream in=new ObjectInputStream(socket.getInputStream());
ObjectOutputStream out=new ObjectOutputStream(socket.getOutputStream());
2.问题:
当程序调用socket.getInputStream()程序被被卡住。
3.原因:
socket.getInputStream()方法会导致程序阻塞,直到inputStream收到对方发过来的报文消息,程序才会继续往下执行。
4.解决办法:
用线程的方式处理输入流。以下为示例代码:
//===============客户端代码 SocketClient.java=====================
-
import
java.io.IOException; -
import
java.io.ObjectInputStream; -
import
java.io.ObjectOutputStream; -
import
java.net.Socket; -
import
java.net.UnknownHostException; -
-
-
public
class SocketClient { -
private Socket socket; -
private ObjectOutputStream out; -
private ObjectInputStream in; -
-
public SocketClient(){ -
try { -
socket=new Socket( "localhost",8081); -
out=new ObjectOutputStream(socket.getOutputStream()); -
ReadThread readThread=new ReadThread(); -
readThread.start(); -
} catch (UnknownHostException e) { -
e.printStackTrace(); -
} catch (IOException e) { -
e.printStackTrace(); -
} -
} -
-
public void sendMessage(String msg){ -
System.out.println("send message:" +msg); -
try { -
out.writeObject(msg); -
out.flush(); -
} catch (IOException e) { -
e.printStackTrace(); -
} -
} -
-
class ReadThread extendsThread{ -
boolean runFlag= true; -
public void run(){ -
try { -
in=new ObjectInputStream(socket.getInputStream()); -
} catch (IOException e1) { -
e1.printStackTrace(); -
} -
while(runFlag){ -
if(socket.isClosed()){ -
return; -
} -
try { -
Object obj=in.readObject(); -
if(obj instanceof String){ -
System.out.println("Client recive:" +obj); -
} -
} -
catch (IOException e) { -
e.printStackTrace(); -
} -
catch (ClassNotFoundException e) { -
e.printStackTrace(); -
} -
} -
} -
-
public void exit(){ -
runFlag=false; -
} -
} -
-
public static void main(String[] args) { -
SocketClient socketClient=new SocketClient(); -
System.out.println("build socketClient" ); -
try { -
Thread.sleep(1000); -
} catch (InterruptedException e) { -
e.printStackTrace(); -
} -
socketClient.sendMessage("Hello first." ); -
try { -
Thread.sleep(1000); -
} catch (InterruptedException e) { -
e.printStackTrace(); -
} -
socketClient.sendMessage("Hello second." ); -
} -
-
}
//============服务器端代码 SocketService.java===========
-
import
java.io.IOException; -
import
java.io.ObjectInputStream; -
import
java.io.ObjectOutputStream; -
import
java.net.ServerSocket; -
import
java.net.Socket; -
import
java.net.SocketException; -
import
java.util.Date; -
-
public
class SocketService { -
ServerSocket serverSocket; -
-
public SocketService(){ -
try { -
serverSocket=new ServerSocket( 8081); -
while(true){ -
Socket socket=serverSocket.accept(); -
SocketServiceThread sst=new SocketServiceThread(socket); -
sst.start(); -
} -
} catch (IOException e) { -
e.printStackTrace(); -
} -
} -
-
class SocketServiceThread extendsThread{ -
Socket socket; -
ObjectInputStream in; -
ObjectOutputStream out; -
boolean runFlag= true; -
public SocketServiceThread(Socket socket){ -
if(null==socket){ -
runFlag=false; -
return; -
} -
this.socket=socket; -
try { -
out=new ObjectOutputStream(socket.getOutputStream()); -
} catch (IOException e) { -
e.printStackTrace(); -
} -
} -
-
public void run(){ -
if(null==socket){ -
System.out.println("socket is );null" -
return; -
} -
try { -
in=new ObjectInputStream(socket.getInputStream()); -
while(runFlag){ -
if(socket.isClosed()){ -
System.out.println("socket is );closed" -
return; -
} -
try { -
String obj=(String)in.readObject(); -
if(obj instanceof String){ -
System.out.println("Server recive:" +obj); -
Date date=new Date(); -
out.writeObject("["+date+"]"+obj); -
out.flush(); -
} -
else{ -
System.out.println("Server recive:" +obj); -
} -
} -
catch (ClassNotFoundException e) { -
e.printStackTrace(); -
} -
catch (SocketException e){ -
e.printStackTrace(); -
return; -
} -
catch (IOException e){ -
e.printStackTrace(); -
} -
} -
} catch (IOException e1) { -
e1.printStackTrace(); -
return; -
} catch (Exception e){ -
return; -
} -
} -
-
public void exit(){ -
runFlag=false; -
} -
} -
-
public static void main(String[] args) { -
System.out.println("===============start service===============" ); -
new SocketService(); -
} -
-
}
5.Socket通信注意事项
(1).writeXXX()方法后一般用flush()来把缓存内容发送出去。
(2).发送对象时,对象必须串行化,即该对象需要实现Serializable接口。
6.参考文献

加载中…