Java Socket編程

jopen 10年前發布 | 19K 次閱讀 Java開發 java socket

Java Socket編程

       對于Java Socket編程而言,有兩個概念,一個是ServerSocket,一個是Socket。服務端和客戶端之間通過Socket建立連接,之后它們就可以進行通信了。首先ServerSocket將在服務端監聽某個端口,當發現客戶端有Socket來試圖連接它時,它會accept該Socket的連接請求,同時在服務端建立一個對應的Socket與之進行通信。這樣就有兩個Socket了,客戶端和服務端各一個。

       對于Socket之間的通信其實很簡單,服務端往Socket的輸出流里面寫東西,客戶端就可以通過Socket的輸入流讀取對應的內容。Socket與Socket之間是雙向連通的,所以客戶端也可以往對應的Socket輸出流里面寫東西,然后服務端對應的Socket的輸入流就可以讀出對應的內容。下面來看一個服務端與客戶端通信的例子:

多個客戶端連接同一個服務端

每次ServerSocket</span>接收到一個新的Socket</span>連接請求后都會新起一個線程來跟當前Socket</span>進行通信,這樣就達到了異步處理與客戶端Socket</span>進行通信的情況。我們使用</span>BufferedReader</span>來一次讀一行,而不是一次讀多少字節</span>

    import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {  

       public static void main(String args[]) throws IOException {  
          //為了簡單起見,所有的異常信息都往外拋  
         int port = 8899;  
          //定義一個ServerSocket監聽在端口8899上  
         ServerSocket server = new ServerSocket(port);  
          while (true) {  
             //server嘗試接收其他Socket的連接請求,server的accept方法是阻塞式的  
             Socket socket = server.accept();  
             //每接收到一個Socket就建立一個新的線程來處理它  
             new Thread(new Task(socket)).start();  
          }  
       }  

       /** 
        * 用來處理Socket請求的 
       */  
       static class Task implements Runnable {  

          private Socket socket;  

          public Task(Socket socket) {  
             this.socket = socket;  
          }  

          public void run() {  
             try {  
                handleSocket();  
             } catch (Exception e) {  
                e.printStackTrace();  
             }  
          }  

          /** 
           * 跟客戶端Socket進行通信 
          * @throws Exception 
           */  
          private void handleSocket() throws Exception {  
             BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));  
             StringBuilder sb = new StringBuilder();  
             String temp;  
             int index;  
             while ((temp=br.readLine()) != null) {  
                System.out.println(temp);  
                if ((index = temp.indexOf("eof")) != -1) {//遇到eof時就結束接收  
                 sb.append(temp.substring(0, index));  
                    break;  
                }  
                sb.append(temp);  
             }  
             System.out.println("from client: " + sb);  
             //讀完后寫一句  
           Writer writer = new OutputStreamWriter(socket.getOutputStream());  
             writer.write("Hello Client.");  
             writer.write("eof\n");  
             writer.flush();  
             writer.close();  
             br.close();  
             socket.close();  
          }  
       }  
    }  </pre><a class="CopyToClipboard" title="copy" href="/misc/goto?guid=4959614076459317529"></a></div>

</div> </div>
這個時候需要注意的是,BufferedReader</span>readLine</span>方法是一次讀一行的,這個方法是阻塞的,直到它讀到了一行數據為止程序才會繼續往下執行,那么readLine</span>什么時候才會讀到一行呢?直到程序遇到了換行符或者是對應流的結束符</span>readLine</span>方法才會認為讀到了一行,才會結束其阻塞,讓程序繼續往下執行。所以我們在使用BufferedReader</span>readLine</span>讀取數據的時候一定要記得在對應的輸出流里面一定要寫入換行符(流結束之后會自動標記為結束,readLine</span>可以識別),寫入換行符之后一定記得如果輸出流不是馬上關閉的情況下記得flush</span>一下,這樣數據才會真正的從緩沖區里面寫入。對應上面的代碼我們的客戶端程序應該這樣寫:</span>


客戶端:

假設有這樣一種需求,我們的客戶端需要通過Socket從服務端獲取到XX信息,然后給用戶展示在頁面上。我們知道Socket在讀數據的時候是阻塞式的,如果沒有讀到數據程序會一直阻塞在那里。在同步請求的時候我們肯定是不能允許這樣的情況發生的,這就需要我們在請求達到一定的時間后控制阻塞的中斷,讓程序得以繼續運行。Socket為我們提供了一個setSoTimeout()方法來設置接收數據的超時時間,單位是毫秒。當設置的超時時間大于0,并且超過了這一時間Socket還沒有接收到返回的數據的話,Socket就會拋出一個SocketTimeoutException。

       假設我們需要控制我們的客戶端在開始讀取數據10秒后還沒有讀到數據就中斷阻塞的話我們可以這樣做:


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.Socket;
import java.net.SocketTimeoutException;

public class Client {

   public static void main(String args[]) throws Exception {  
      //為了簡單起見,所有的異常都直接往外拋  
     String host = "127.0.0.1";  //要連接的服務端IP地址  
     int port = 8899;   //要連接的服務端對應的監聽端口  
     //與服務端建立連接  
     Socket client = new Socket(host, port);  
      //建立連接后就可以往服務端寫數據了  
     Writer writer = new OutputStreamWriter(client.getOutputStream());  
      writer.write("Hello Server.");  
      writer.write("eof\n");  
      writer.flush();  
      //寫完以后進行讀操作  
     BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));  
      //設置超時間為10秒  
     client.setSoTimeout(10*1000);  
      StringBuffer sb = new StringBuffer();  
      String temp;  
      int index;  
      try {  
         while ((temp=br.readLine()) != null) {  
            if ((index = temp.indexOf("eof")) != -1) {  
                sb.append(temp.substring(0, index));  
                break;  
            }  
            sb.append(temp);  
         }  
      } catch (SocketTimeoutException e) {  
         System.out.println("數據讀取超時。");  
      }  
      System.out.println("from server: " + sb);  
      writer.close();  
      br.close();  
      client.close();  
   }  
}  

</pre> 
</span>



來自:http://haohaoxuexi.iteye.com/blog/1979837 

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!