Java 記一次 socket 互傳數據時出現的輸出流阻塞bug

事情是這樣的,我使用socket來基於http協議來傳輸POST請求,那麼POST請求一定要發送在http協議的正文部分,可是奇怪的是無論如何服務端都收不到POST請求的內容,線程一直阻塞在【等待http協議的正文】部分

下面給出相關的代碼

http服務端

InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));

String line=null, uri=null, method=null;
// 讀取客戶端請求 接收並分析包頭信息
while((line=reader.readLine()).length() != 0) {
	System.out.println("接收到的包頭: " + line);
	// 只處理GET POST HEAD請求
	if(line.split(" ")[0].equals("GET") || 
	   line.split(" ")[0].equals("POST") ||
	   line.split(" ")[0].equals("HEAD")) {
		// 提取請求的uri
		uri = line.split(" ")[1];
		method = line.split(" ")[0];
		System.out.println("接收到" + method +"請求, uri=" + uri);
	}
}
System.out.println("--- 包頭接收完成 ---");

// 接收POST請求的內容,即http包頭之後的部分,程序一直阻塞在這裏
line = reader.readLine();

http客戶端

URLConnection  con = new URL(url).openConnection();
con.setDoOutput(true);	// 設置請求爲可寫
con.connect();

// 輸出流寫post報文內容,就是這裏一直無法輸出
String queryStr = "key1=aaa&value1=bbb";
OutputStream os = con.getOutputStream();
os.write(queryStr.getBytes());	// 在http協議內容中發送post請求字符串
os.flush();
os.close();

思前向後不對啊,不可能啊

然後我自己又另外寫了個socket通過字節傳輸,發現沒問題,可以收到,難道是BufferedReader的問題?

後面發現還真是,因爲客戶端發送請求是以字節流的形式,而服務端因爲字符串方便操作,所以選用BufferedReader來讀取字符串,注意到這個方法:

readLine()

看到函數名字我秒懂了,readLine,讀一行,我這queryStr沒有換行符,所以程序認爲讀不到換行不結束,就一直阻塞,把queryStr 加上換行就行了

String queryStr = "key1=aaa&value1=bbb";
queryStr += "\r\n";

總結

使用不同的流傳輸數據的時候,一定切記維護雙方的接收形式

比如字符流,readLine的話,就要以回車結束,如果是字節流,直接關閉socket即可,系統底層會發送一個-1(255)表示發送結束

如果雙方判斷結束的方式不同,那麼很可能會造成輸入輸出流的阻塞

使用http協議的時候,最好:每寫一句就換行

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章