Java 客戶端伺服器範例
阿新 • • 發佈:2018-11-08
最近在面試,雖然學習了一些新的框架,但是可能問類似於客戶端伺服器模型,然後根據其設計,所以就根據面試內容梳理一下客戶端伺服器模型。
客戶端基本思路:
1.建立Socket例項,設定埠和IP地址等
2.通過Socket例項,獲取到流物件
3.通過流物件,向其中輸入資料 ,並且在完成後實現關閉流。
(注意事情:1.需要進行異常處理 2.注意關閉流和Socket 3.低階流和高階流的關閉順序)
//客戶端程式 package ServerSocket; import java.io.BufferedOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; public class ClientDome { public static void main(String[] args) { Socket socket =null; OutputStream outputStream=null; BufferedOutputStream bufferedOutputStream=null; try { socket=new Socket("localhost", 6060); outputStream=socket.getOutputStream(); bufferedOutputStream =new BufferedOutputStream(outputStream); String str ="Client Dome ..... Are you ok"; bufferedOutputStream.write(str.getBytes()); bufferedOutputStream.flush(); } catch (Exception e) { e.printStackTrace(); }finally{ try { bufferedOutputStream.close(); outputStream.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } } }
伺服器模型構建:
1.建立一個ServerSocket物件,進行埠監聽。
2.while(true)重複監聽
3.通過埠監聽物件 獲取Socket例項 並且獲取到網路流
4.輸出網路流資料 並且關閉流
(注意事情:埠監聽一次 獲取監聽物件多次 低階流和高階流的關閉順序)
//首先這是單執行緒版本 package ServerSocket; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; public class ServerSocketDome { @SuppressWarnings("null") public static void main(String[] args) { // 1.建立監聽 ServerSocket serverSocket = null; InputStream inputStream = null; BufferedInputStream bufferedInputStream = null; @SuppressWarnings("unused") Socket socket = null; try { serverSocket =new ServerSocket(6060); while(true){ socket = serverSocket.accept(); inputStream = socket.getInputStream(); bufferedInputStream = new BufferedInputStream(inputStream); byte[] bytes=new byte[10]; int len=0; while((len=bufferedInputStream.read(bytes))!=-1){ System.out.print(new String(bytes, 0, len)); } } } catch (IOException e) { e.printStackTrace(); } finally { try { if(bufferedInputStream!=null){ bufferedInputStream.close(); inputStream.close(); socket.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
多執行緒版本怎麼操作,這裡即將引入多執行緒
伺服器版本多執行緒主要是對於請求分執行緒操作 ,一次連線會單獨分配執行緒
package ServerSocket; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; //為了應對面試需要 嘗試根據自己思路寫一個新的多執行緒版本試試 //其實多執行緒版本是根據單執行緒改進而來 //具體而言 多執行緒的伺服器 是應對多條請求 不同執行緒進行處理 public class ServerSocketThreadDome { public static void main(String[] args) { //當然 主執行緒的埠監聽是不能修改的 ServerSocket serverSocket = null; //標準web伺服器的埠是8080 int port=6060; try { serverSocket=new ServerSocket(port); Socket socket=null; while(true){ socket=serverSocket.accept(); new Thread(new Server(socket)).start(); } } catch (IOException e) { e.printStackTrace(); }finally{ if(serverSocket!=null){ try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } } } //這裡的多執行緒說白了 就是為了應對多條請求而處理的結果 //也就是客戶端物件 class Server implements Runnable{ private Socket socket; public Server(Socket socket) { super(); this.socket = socket; } @Override public void run() { InputStream inputStream=null; BufferedInputStream bufferedInputStream =null; try { inputStream = socket.getInputStream(); bufferedInputStream=new BufferedInputStream(inputStream); byte[] bytes=new byte[1024]; int len=0; while((len=bufferedInputStream.read(bytes))!=-1){ System.out.print(new String(bytes, 0, len)); System.out.println("當前執行緒:"+Thread.currentThread().getName()); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ try { if(bufferedInputStream!=null){ bufferedInputStream.close(); inputStream.close(); socket.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
那麼我們引入執行緒池的概念 有時候面試可能會問執行緒池
package ServerSocket; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; //首先大話一下執行緒池,執行緒池類似於中介結果,我需要的時候找中介借一些人過來 //不需要的時候中介自己回去 我不需要提供其他待遇等等 //就是傳說中的國企或者大型企業的外包部門 public class ServerSocketPoolDome { public static void main(String[] args) { ServerSocket serverSocket = null; //標準web伺服器的埠是8080 int port=6060; try { serverSocket=new ServerSocket(port); Socket socket=null; ExecutorService executorService =Executors.newCachedThreadPool(); while(true){ socket=serverSocket.accept(); executorService.execute(new ServerPool(socket)); } } catch (IOException e) { e.printStackTrace(); }finally{ if(serverSocket!=null){ try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } } } //這裡的多執行緒說白了 就是為了應對多條請求而處理的結果 //也就是客戶端物件 class ServerPool implements Runnable{ private Socket socket; public ServerPool(Socket socket){ super(); this.socket = socket; } @Override public void run() { InputStream inputStream=null; BufferedInputStream bufferedInputStream =null; try { inputStream = socket.getInputStream(); bufferedInputStream=new BufferedInputStream(inputStream); byte[] bytes=new byte[1024]; int len=0; while((len=bufferedInputStream.read(bytes))!=-1){ System.out.print(new String(bytes, 0, len)); System.out.println("當前執行緒:"+Thread.currentThread().getName()); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ try { if(bufferedInputStream!=null){ bufferedInputStream.close(); inputStream.close(); socket.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
執行緒池的使用很爽,接下來看看執行緒池的原始碼
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); } //執行緒池建立一個緩衝的執行緒池
//也就設定執行緒數目 和 活動時間 以及具體執行的方式