標籤:socket java read阻塞
Socket的可寫狀態和可讀狀態。當輸出緩衝區未滿時,Socket是可寫的(注意,不是對方啟用接收操作後,本地才能可寫,這是錯誤的理解),因此,當通訊端被建立時,即處於可寫的狀態。對於可讀,則是指緩衝區中有接收到的資料,並且這些資料未完成處理。在socket建立時,並不處於可讀狀態,僅當串連的另一方向本通訊端的通道寫入資料後,本通訊端方能處於可讀狀態(注意,如果對方通訊端已經關閉,那麼本地通訊端將處於可讀狀態,並且每次調用read後,返回的都是-1)。
import java.net.*;import java.io.*;public class Server{ public static void main(String[] args) throws Exception { ServerSocket server = new ServerSocket(8888); System.out.println("Wait for connection..."); Socket socket = server.accept(); BufferedInputStream is = new BufferedInputStream(socket.getInputStream()); byte[] buff = new byte[1024]; int size; //當用戶端的輸出資料流沒有close時,伺服器端收不到-1,會一直在沉睡在while裡面, while((size = is.read(buff)) != -1){ String str = new String(buff,0,size); System.out.println(str); /****************************************************/ if(str.indexOf(‘\n‘) > 0){//存在訊息結束標誌 break; } /*****************************************************/ } //is.close(); System.out.println("Received"); System.out.println("Sending..."); BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream()); out.write("你好,我是伺服器".getBytes()); out.flush(); out.close(); is.close(); socket.close(); System.out.println("Send Over!"); }}
import java.net.*;import java.io.*;public class Client{ public static void main(String[] args) throws Exception { Socket socket = new Socket("localhost",8888); BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream()); /********************表示發送結束*****************************/ out.write("你好,我是用戶端\n".getBytes()); out.flush(); //out.close();有這句話時,伺服器可以讀到一個-1 System.out.println("Send Over!"); System.out.println("Receiving..."); BufferedInputStream is = new BufferedInputStream(socket.getInputStream()); byte[] buff = new byte[1024]; int size; while((size = is.read(buff)) != -1){ System.out.println(new String(buff,0,size)); } is.close(); out.close(); socket.close(); System.out.println("Received!"); }}
1、伺服器偵聽
2、用戶端發送了串連請求,然後發送資料(未關閉串連);
3、伺服器收到資料,但是讀不到-1,陷入睡眠(用戶端尾關閉串連,伺服器讀不到-1)
4、用戶端收不到資料,也睡在了read裡面
5、由於兩者的沉睡,陷入了死迴圈
解決方案:
1、在用戶端發送資料時,加一個結尾標誌,伺服器端檢測這個標誌
2、使用DataXXXStream封裝資料流
java網路編程中的read阻塞問題