不寫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在操作字符的時候有很多更直觀的接口以供調用,使用過程中需仔細注意