java的Socket

java API爲咱們網絡通訊提供了服務器套接字ServerSocket類和客戶端套接字Socket,Socket是網絡驅動層提供給應用程序編程的接口和一種機制。
下面提供具體實現例子

服務端--ServerSocket
     ServerSocket類實現了服務器的套接字,主要方法
ServerSocket(int port)-----建立綁定到特定端口的服務器套接字
void setSoTimeout(timeout);----指定超時時間
InetAdress getInetAddress()----返回此服務器套接字的本機地址
Socket accept()--------------偵聽並接受此套接字的鏈接

示例代碼:
  1. package com;  
  2.   
  3. import java.io.BufferedInputStream;  
  4. import java.io.BufferedOutputStream;  
  5. import java.io.IOException;  
  6. import java.net.ServerSocket;  
  7. import java.net.Socket;  
  8.   
  9.   
  10. public class Test {  
  11.   
  12.     public static void main(String[] args) {  
  13.           
  14.         try {  
  15.             ServerSocket server=new ServerSocket(8080);  
  16.             //等待客戶端鏈接  
  17.             while(true){  
  18.                 Socket client=server.accept();  
  19.                 //每一個客戶端創建一個線程  
  20.                 new Thread(new myRunnable(client)).start();;  
  21.             }  
  22.               
  23.         } catch (IOException e) {  
  24.             e.printStackTrace();  
  25.         }  
  26.       
  27.     }  
  28.       
  29. }  
  30.   
  31. class myRunnable implements Runnable{  
  32.       
  33.     private Socket socket;  
  34.       
  35.     public myRunnable(Socket s)  
  36.     {  
  37.         this.socket=s;  
  38.     }  
  39.     //----run方法運行完畢,線程正常結束  
  40.     @Override  
  41.     public void run() {  
  42.           
  43.         try {  
  44.             //接收客戶端數據  
  45.             BufferedInputStream is=new BufferedInputStream(socket.getInputStream());              
  46.             int data=is.read()+1;//把客戶的數據加一  
  47.               
  48.             Thread.sleep(1000);//休眠一秒  
  49.             //輸出到客戶端  
  50.             BufferedOutputStream os=new BufferedOutputStream(socket.getOutputStream());           
  51.             os.write(data);//返回數據給客戶端  
  52.               
  53.             os.close();       
  54.             os.close();  
  55.                           
  56.         } catch (IOException | InterruptedException e) {  
  57.             e.printStackTrace();  
  58.         }  
  59.           
  60.           
  61.     }  
  62.       
  63. }  
複製代碼
客戶端----Socket
Socket類實現客戶端套接字,套接字是兩臺機器間通訊的端點,主要方法有

Socket(String host,int port)----建立一個套接字將其鏈接到指定主機的指定端口號
InputStream getInputStream()----返回此套接字的輸入流
OutputStream getOutputStream()----返回此套接字的輸出流

示例代碼:
  1. package com;  
  2.   
  3. import java.io.BufferedInputStream;  
  4. import java.io.BufferedOutputStream;  
  5. import java.io.IOException;  
  6. import java.net.Socket;  
  7. import java.net.UnknownHostException;  
  8.   
  9. public class Client {  
  10.   
  11.     public static void main(String[] args) {  
  12.   
  13.         for(int i=0;i<20;i++)  
  14.         {  
  15.   
  16.             try {  
  17.                 Socket socket = new Socket("localhost", 8080);  
  18.                 //輸出到服務器  
  19.                 BufferedOutputStream os=new BufferedOutputStream(socket.getOutputStream());               
  20.                 os.write(i);              
  21.                 os.flush();  
  22.                 //os.close();不能再這裏關閉流,關閉流會致使socket也關閉  
  23.   
  24.                 // 構建字符緩衝流  
  25.                 BufferedInputStream is=new BufferedInputStream(socket.getInputStream());  
  26.                   
  27.                 int data=is.read();       
  28.                 is.close();  
  29.                   
  30.                 os.close();  
  31.                   
  32.                 System.out.println(data);             
  33.             } catch (UnknownHostException e) {  
  34.                 e.printStackTrace();  
  35.             } catch (IOException e) {  
  36.                 e.printStackTrace();  
  37.             }  
  38.         }  
  39.           
  40.     }  
  41.   
  42. }  
複製代碼
主要不能提早關閉輸入輸出流,關閉輸入輸出流會致使Socket關閉


能夠引發網絡鏈接關閉的狀況有如下4種:

1.直接調用Socket類的close方法。

2.只要Socket類的InputStream和OutputStream有一個關閉,網絡鏈接自動關閉(必須經過調用InputStream和OutputStream的 close方法關閉流,才能使網絡可愛接自動關閉)。

3.在程序退出時網絡鏈接自動關閉。
4.將Socket對象設爲null或未關閉最使用new Socket(…)創建新對象後,由JVM的垃圾回收器回收爲Socket對象分配的內存空間後自動關閉網絡鏈接。

線程池
   在處理多個客戶端時是爲每個鏈接建立一個線程,然而頻繁的線程建立會影響性能,因此咱們可使用線程池來解決頻線程的建立問題。

線程池:線程池是一種預先建立線程的一種技術。線程池在任務還沒到來以前,建立必定數量的線程,放到空閒隊列,而後對這些資源進行復用,減小頻繁的線程建立和銷燬。

        JDK1.5版本後提供了線程池,線程池的頂級接口是Executor,是一個執行工具,線程池的直接接口是ExecutorService,是併發開發中經常使用的工具類

      要配置一個線程池是比較複雜的,尤爲是對於線程池的原理不是很清楚的狀況下,頗有可能配置的線程池不是較優的,所以在Executors類裏面提供了一些靜態工廠,生成一些經常使用的線程池。

1. newSingleThreadExecutor

建立一個單線程的線程池。這個線程池只有一個線程在工做,也就是至關於單線程串行執行全部任務。若是這個惟一的線程由於異常結束,那麼會有一個新的線程來替代它。此線程池保證全部任務的執行順序按照任務的提交順序執行。

2. newFixedThreadPool

建立固定大小的線程池。每次提交一個任務就建立一個線程,直到線程達到線程池的最大大小。線程池的大小一旦達到最大值就會保持不變,若是某個線程由於執行異常而結束,那麼線程池會補充一個新線程。

3. newCachedThreadPool

建立一個可緩存的線程池。若是線程池的大小超過了處理任務所須要的線程,

那麼就會回收部分空閒(60秒不執行任務)的線程,當任務數增長時,此線程池又能夠智能的添加新線程來處理任務。此線程池不會對線程池大小作限制,線程池大小徹底依賴於操做系統(或者說JVM)可以建立的最大線程大小。

4. newScheduledThreadPool
建立一個大小無限的線程池。此線程池支持定時以及週期性執行任務的需求。

此時咱們在服務器的用上線程池,使用newFixedThreadPool,代碼改成
Java代碼  [url=][/url]
  1. package com;  
  2.   
  3. import java.io.BufferedInputStream;  
  4. import java.io.BufferedOutputStream;  
  5. import java.io.IOException;  
  6. import java.net.ServerSocket;  
  7. import java.net.Socket;  
  8.   
  9. import java.util.concurrent.ExecutorService;  
  10. import java.util.concurrent.Executors;  
  11.   
  12.   
  13. public class Test {  
  14.   
  15.     public static void main(String[] args) {  
  16.           
  17.         try {  
  18.             ServerSocket server=new ServerSocket(8080);  
  19.             //獲取cpu數  
  20.             int cpu_Num=Runtime.getRuntime().availableProcessors();  
  21.             //建立指定大小的線程池  
  22.             ExecutorService es=Executors.newFixedThreadPool(cpu_Num);  
  23.             //等待客戶端鏈接  
  24.             while(true){  
  25.                 Socket client=server.accept();  
  26.                 //每一個客戶端創建一個線程  
  27.                 //new Thread(new myRunnable(client)).start();  
  28.                 es.execute(new myRunnable(client));  
  29.             }  
  30.               
  31.         } catch (IOException e) {  
  32.             e.printStackTrace();  
  33.         }  
  34.       
  35.     }  
  36.       
  37. }  
  38.   
  39. class myRunnable implements Runnable{  
  40.       
  41.     private Socket socket;  
  42.       
  43.     public myRunnable(Socket s)  
  44.     {  
  45.         this.socket=s;  
  46.     }  
  47.     //----run方法運行完畢,線程正常結束  
  48.     @Override  
  49.     public void run() {  
  50.           
  51.         try {  
  52.             //接收客戶端數據  
  53.             BufferedInputStream is=new BufferedInputStream(socket.getInputStream());              
  54.             int data=is.read()+1;//把客戶的數據加一  
  55.               
  56.             Thread.sleep(1000);//休眠一秒  
  57.             //輸出到客戶端  
  58.             BufferedOutputStream os=new BufferedOutputStream(socket.getOutputStream());           
  59.             os.write(data);//返回數據給客戶端  
  60.               
  61.             os.close();       
  62.             os.close();  
  63.                           
  64.         } catch (IOException | InterruptedException e) {  
  65.             e.printStackTrace();  
  66.         }  
  67.           
  68.           
  69.     }  
  70.       
  71. }  
複製代碼
這樣雖然現實了併發服務器,但這樣的服務器效率低,吞吐量低,想提升服務器性能,能夠研究學習java的nio和aio,能大大提高服務器性能。
相關文章
相關標籤/搜索