socket 簡要總結

先開啓服務端,再開啓客戶端,否則Connection refused

如果客戶端沒有發送結束標識,如socket.shutdownOutput()或者socket.close(),服務端讀取數據Connection reset,反之亦然

客戶端Client的時候, 如果存在網絡問題, 爲了避免網絡問題,造成客戶端長時間等待, 此時要設置一個TimeOut

clientSocket = new Socket();
 //這個TimeOut是連接等待時間
clientSocket.connect(tcpAddress, timeOut);
  1. 當客戶端已經連接, 每次收到一個數據, 客戶端將啓動處理, 假如服務器長久不發數據, 此時客戶端會阻塞等待, 爲了避免這個時候的等待, 可以設置一個超時
clientSocket.setSoTimeout(timeOut);

如何告知對方已發送完命令

socket 關閉
socket.close()  
  • socket關閉連接,那邊如果有服務端給客戶端反饋信息,此時客戶端是收不到的

  • 如果客戶端想再次發送消息,需要重現創建Socket連接

    通過Socket關閉輸出流的方式
socket.shutdownOutput() 

而不是outputStream.close() (outputStream爲發送消息到服務端打開的輸出流)):

outputStream.close();

如果關閉了輸出流,那麼相應的Socket也將關閉,和直接關閉Socket一個性質

socket.shutdownOutput()是將客戶端輸出流關閉,此時,如果服務端有信息返回,則客戶端是可以正常接受的,如果沒有,直接關閉Socket

  • 不能再次發送消息給服務端,如果再次發送,需要重新建立Socket連接
通過約定符號

雙方約定一個字符或者一個短語,來當做消息發送完成的標識,通常這麼做就需要改造讀取方法

假如約定單端的一行爲end,代表發送完成,例如下面的消息,end則代表消息發送完成:

hello wakala
end

服務端讀取操作:

Socket socket = server.accept();
// 建立好連接後,從socket中獲取輸入流,並建立緩衝區進行讀取
BufferedReader read=new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
String line;
StringBuilder sb = new StringBuilder();
while ((line = read.readLine()) != null && "end".equals(line)) {
  //注意指定編碼格式,發送方和接收方一定要統一,建議使用UTF-8
  sb.append(line);
}
通過指定長度

記錄異常:Connection reset

當客戶端用readLine讀取數據時,readline()方法會讀到流結束或者\n的時候返回

客戶端:
InputStream inputStream = socket.getInputStream();
 BufferedReader bufferedReader = new BufferedReader(new         InputStreamReader(inputStream,DEFAULT));
            StringBuilder builder = new StringBuilder();
            String line = bufferedReader.readLine();
            builder.append(line);
服務端:
String linebreak = System.getProperty("line.separator","\n");
OutputStream outputStream = socket.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new     OutputStreamWriter(outputStream));
bufferedWriter.write("response");
   // bufferedWriter.write(linebreak);//添加換行符
bufferedWriter.flush();

服務端如果不關閉輸出流或者在消息的結尾沒有發送換行符\n時,客戶端會報Connection reset

如果消息加了換行符,並且服務端沒有關閉,在客戶端讀取時,這樣寫同樣會報錯:


InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new        InputStreamReader(inputStream));
 StringBuilder builder = new StringBuilder();
 String line;
    while ((line = bufferedReader.readLine())!= null){
       builder.append(line);
    }  
 //因爲 第一次bufferedReader.readLine()已經讀完,socket連接已經釋放,再次在while()中讀取就會 //Connection reset
// 所以去掉while循環, 
 StringBuilder builder = new StringBuilder();
 String line = bufferedReader.readLine();
 builder.append(line);
    
  還有:
  //客戶端這種方式讀取,服務端不需要加換行符號
 byte[] bytes = new byte[1024];
  int len;
  StringBuilder sb = new StringBuilder();
  while ((len = inputStream.read(bytes))!= - 1){
          String part = new String(bytes,0,len,DEFAULT);
         //println("result part=="+part);
          sb.append(part);
   }
  客戶端一直讀取也會報Connection reset
 解決方法:
 判斷inputStream.available()方法,這種方法在讀寫操作前先得知數據流裏有多少個字節可以讀取
  byte[] bytes = new byte[1024];
        do{
                 len = inputStream.read(bytes);
                 if (len!=-1){
                     String sss = new String(bytes,0,len,DEFAULT);
                     println("result part=="+sss);
                     sb.append(sss);
                 }
              }while(inputStream.available()!= 0);
 
 

參考:JAVA通信系列一:Java Socket技術總結

Java Socket編程基礎及深入講解

Connection reset :readline 引起的socket讀取異常

Socket的長連接和短連接

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