java編寫socket使用bufferedReader.readLine()問題研究


不寫java代碼好久,臨時寫個socket通訊竟然失敗,郁悶之下仔細研究了下。

客戶端使用BufferedReader來讀取數據,在while中調用BufferedReader.readLine()函數,結果程序運行起來之后一直死等,就是不輸出想要的結果。

google發現 readLine()方式是讀行的,所以只有遇到換行符或者流結束的時候才會得到結果,在window系統下使用"\r\n"代替換行符,驗證ok。

即在我們一般的服務端輸出信息

printWriter.write("news");

//輸入換行符並發送到客戶端

printWriter.write("\r\n");

printWriter.flush();

下面附上幾個簡單源碼:小弟這里是用來解決flex調用socket垮與文件許可的,所以下面內容也是以此為例,服務需支持多次調用,客戶端接收到跨域文件后則關閉

首先是最直接的,不使用BufferedReader(),個人感覺這個更簡單清晰些

服務端,客戶端都使用DataInputStream; DataOutputStream();

服務代碼:

public class Server {
	public static void main(String args[]){
		try {
			DataInputStream din;
			DataOutputStream dout;
			
			ServerSocket server = new ServerSocket(4444);
			
			while(true){
				Socket client = server.accept();
				din  = new DataInputStream(client.getInputStream());
				dout = new DataOutputStream(client.getOutputStream());
				
				String s;
				if((s = din.readUTF()) != null){
					System.out.println(s);
				}
				
				if(s.equals("<policy-file-request/>")){
					String msg = "<?xml version=\"1.0\"?>" + "<cross-domain-policy>" 
					+ "<site-control permitted-cross-domain-policies=\"all\"/>"
					+ "<allow-access-from domain=\"*\" to-ports=\"*\" />"
					+ "</cross-domain-policy>";
					dout.writeUTF(msg);
				}
				din.close();
				dout.close();
				client.close();
			}
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
}

客戶端:

public class Client {

	public static void main(String args[]){
		
		DataInputStream din;
		DataOutputStream dout;
		try {
			Socket client = new Socket("127.0.0.1", 2000);
			
			din  = new DataInputStream(client.getInputStream());
			dout = new DataOutputStream(client.getOutputStream());
			dout.writeUTF("<policy-file-request/>");
			
			String s = null;
			if((s=din.readUTF()) != null){
				System.out.println(s);
			}
			din.close();
			dout.close();
			client.close();
	            
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
	}
}

 

更換客戶端接收為BufferedReader,使用readLine()方法。如果繼續使用上面的服務,那么依然是沒有錯的....因為上面的服務段在信息輸出之后理科調用了dout.colse方法。正如我們開始說的,當流結束的時候readLine()方法也能讀取到結果。  如果是想實現一個客戶端和服務端保持連接一直交互通訊的功能,那么請在上面的信息輸入完成后添加如下代碼

 

dout.writeUTF(msg);//補充
//因為在客戶端使用bufferedReader.readLine()在讀取,這里必須輸入換行符,
//並且調用fluesh(),方法。否則客戶端將陷入死等狀態
dout.writeUTF("\r\n");
dout.flush();

 

此時客戶端代碼如下:

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;


public class Client {

	public static void main(String args[]){

		DataOutputStream dout;
		BufferedReader br;
		PrintWriter out;
		try {
			Socket client = new Socket("127.0.0.1", 4444);
			
			br  = new BufferedReader(new InputStreamReader(client.getInputStream(),"UTF-8"));
			dout = new DataOutputStream(client.getOutputStream());
			dout.writeUTF("<policy-file-request/>");
			
			String s = null;
			while(true){
				s = br.readLine();
				if(s != null){
					System.out.println(s);
					break;
				}
			}
			
			br.close();
			dout.close();
			client.close();
	            
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
	}
}

 

最后,總結兩點:

一、readLine()方法,需要明確換行符或者結束符,信息需要flush()才能接受到,增加了兩端的信息輸入(多輸入換行符,並且這個符號不同系統是不一樣的)

二,任何流進行寫入完成后請調用flush()方法推送下。  以確保正確性

當然bufferedReader在操作字符的時候有很多更直觀的接口以供調用,使用過程中需仔細注意

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM