加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

【转载】用线程解决Socket的getInputStream阻塞

(2014-05-15 09:04:14)
分类: 应用系统、编程方面

1.背景:

在Socket通信中,当我们希望传输对象时,往往会用到输入/输出对象流。

ObjectInputStream in=new ObjectInputStream(socket.getInputStream());

ObjectOutputStream out=new ObjectOutputStream(socket.getOutputStream());

 

2.问题:

当程序调用socket.getInputStream()程序被被卡住。

 

3.原因:

socket.getInputStream()方法会导致程序阻塞,直到inputStream收到对方发过来的报文消息,程序才会继续往下执行。

 public ObjectInputStream(InputStream in) throws IOException的官方API显示:Creates an ObjectInputStream that reads from the specified InputStream. A serialization stream header is read from the stream and verified. This constructor will block until the corresponding ObjectOutputStream has written and flushed the header. [1]

 

4.解决办法:

用线程的方式处理输入流。以下为示例代码:

//===============客户端代码 SocketClient.java=====================

  1. import java.io.IOException;  
  2. import java.io.ObjectInputStream;  
  3. import java.io.ObjectOutputStream;  
  4. import java.net.Socket;  
  5. import java.net.UnknownHostException;  
  6.   
  7.   
  8. public class SocketClient  
  9.     private Socket socket;  
  10.     private ObjectOutputStream out;  
  11.     private ObjectInputStream in;  
  12.       
  13.     public SocketClient(){  
  14.         try  
  15.             socket=new Socket("localhost",8081);  
  16.             out=new ObjectOutputStream(socket.getOutputStream());  
  17.             ReadThread readThread=new ReadThread();  
  18.             readThread.start();  
  19.         catch (UnknownHostException e)  
  20.             e.printStackTrace();  
  21.         catch (IOException e)  
  22.             e.printStackTrace();  
  23.          
  24.      
  25.       
  26.     public void sendMessage(String msg){  
  27.         System.out.println("send message:"+msg);  
  28.         try  
  29.             out.writeObject(msg);  
  30.             out.flush();  
  31.         catch (IOException e)  
  32.             e.printStackTrace();  
  33.          
  34.      
  35.       
  36.     class ReadThread extends Thread{  
  37.         boolean runFlag=true 
  38.         public void run(){  
  39.             try  
  40.                 in=new ObjectInputStream(socket.getInputStream());  
  41.             catch (IOException e1)  
  42.                 e1.printStackTrace();  
  43.              
  44.             while(runFlag){  
  45.                 if(socket.isClosed()){  
  46.                     return 
  47.                  
  48.                 try  
  49.                     Object obj=in.readObject();  
  50.                     if(obj instanceof String){  
  51.                         System.out.println("Client recive:"+obj);  
  52.                      
  53.                   
  54.                 catch (IOException e)  
  55.                     e.printStackTrace();  
  56.                   
  57.                 catch (ClassNotFoundException e)  
  58.                     e.printStackTrace();  
  59.                  
  60.              
  61.          
  62.           
  63.         public void exit(){  
  64.             runFlag=false 
  65.          
  66.      
  67.       
  68.     public static void main(String[] args)  
  69.         SocketClient socketClient=new SocketClient();  
  70.         System.out.println("build socketClient");  
  71.         try  
  72.             Thread.sleep(1000);  
  73.         catch (InterruptedException e)  
  74.             e.printStackTrace();  
  75.          
  76.         socketClient.sendMessage("Hello first.");  
  77.         try  
  78.             Thread.sleep(1000);  
  79.         catch (InterruptedException e)  
  80.             e.printStackTrace();  
  81.          
  82.         socketClient.sendMessage("Hello second.");  
  83.      
  84.   
  85.  

 

//============服务器端代码 SocketService.java===========

  1. import java.io.IOException;  
  2. import java.io.ObjectInputStream;  
  3. import java.io.ObjectOutputStream;  
  4. import java.net.ServerSocket;  
  5. import java.net.Socket;  
  6. import java.net.SocketException;  
  7. import java.util.Date;  
  8.   
  9. public class SocketService  
  10.     ServerSocket serverSocket;  
  11.       
  12.     public SocketService(){  
  13.         try  
  14.             serverSocket=new ServerSocket(8081);  
  15.             while(true){  
  16.                 Socket socket=serverSocket.accept();  
  17.                 SocketServiceThread sst=new SocketServiceThread(socket);  
  18.                 sst.start();  
  19.              
  20.         catch (IOException e)  
  21.             e.printStackTrace();  
  22.          
  23.      
  24.       
  25.     class SocketServiceThread extends Thread{  
  26.         Socket socket;  
  27.         ObjectInputStream in;  
  28.         ObjectOutputStream out;  
  29.         boolean runFlag=true 
  30.         public SocketServiceThread(Socket socket){  
  31.             if(null==socket){  
  32.                 runFlag=false 
  33.                 return 
  34.              
  35.             this.socket=socket;  
  36.             try  
  37.                 out=new ObjectOutputStream(socket.getOutputStream());  
  38.             catch (IOException e)  
  39.                 e.printStackTrace();  
  40.              
  41.          
  42.           
  43.         public void run(){  
  44.             if(null==socket){  
  45.                 System.out.println("socket is null");  
  46.                 return 
  47.              
  48.             try  
  49.                 in=new ObjectInputStream(socket.getInputStream());  
  50.                 while(runFlag){  
  51.                     if(socket.isClosed()){  
  52.                         System.out.println("socket is closed");  
  53.                         return 
  54.                      
  55.                     try  
  56.                         String obj=(String)in.readObject();  
  57.                         if(obj instanceof String){  
  58.                             System.out.println("Server recive:"+obj);  
  59.                             Date date=new Date();  
  60.                             out.writeObject("["+date+"]"+obj);  
  61.                             out.flush();  
  62.                          
  63.                         else 
  64.                             System.out.println("Server recive:"+obj);  
  65.                          
  66.                       
  67.                     catch (ClassNotFoundException e)  
  68.                         e.printStackTrace();  
  69.                      
  70.                     catch (SocketException e){  
  71.                         e.printStackTrace();  
  72.                         return 
  73.                      
  74.                     catch (IOException e){  
  75.                         e.printStackTrace();  
  76.                      
  77.                  
  78.             catch (IOException e1)  
  79.                 e1.printStackTrace();  
  80.                 return 
  81.             catch (Exception e){  
  82.                 return 
  83.              
  84.          
  85.           
  86.         public void exit(){  
  87.             runFlag=false 
  88.          
  89.      
  90.       
  91.     public static void main(String[] args)  
  92.         System.out.println("===============start service===============");  
  93.         new SocketService();  
  94.      
  95.   
  96.  

5.Socket通信注意事项

(1).writeXXX()方法后一般用flush()来把缓存内容发送出去。

(2).发送对象时,对象必须串行化,即该对象需要实现Serializable接口。


6.参考文献

 [1]Socket同时使用ObjectInputStream和ObjectOutputStream传输序列化对象时的顺序


0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有