0. 一個關於C/S架構的比喻 (客戶給汽車充電)java
對照:一個關於TCP協議的比喻 (客戶給汽車充電)服務器
1. ServerSocket 類網絡
<1> java.net.ServerSocket類:用於描述服務器套接字信息(大插排)架構
所謂套接字(Socket),就是對網絡中不一樣主機上的應用進程之間進行雙向通訊的端點的抽象 socket
<2> 經常使用的方法以下:ide
方法聲明 | 功能介紹 |
ServerSocket(int port) | 根據參數指定的端口號,來構造對象 |
Socket accept() | 偵聽,並接收,到此套接字的鏈接請求 |
void close() | 用於關閉套接字 |
2. Socket類this
<1> java.net.Socket類:用於描述客戶端套接字,是兩臺機器間通訊的端點(小插排)。spa
<2> 常見的方法以下:.net
方法聲明 | 功能介紹 |
Socket(String host,int port) | 根據指定主機名 和 端口來構造對象 |
InputStream getInputStream() | 獲取當前套接字的輸入流 |
OutputStream getOutputStream() | 獲取當前套接字的輸出流 |
void close() | 用於關閉套接字 |
<3> 注意事項線程
1. 客戶端Socket 與 服務器端 Socket對應,都包含輸入 和 輸出流
2. 客戶端的socket.getInputStrream() 鏈接於服務器 socket.getOutputStream()
3. 客戶端的socket.getOutputStream()鏈接於服務器socket.getInputStream()
3. 代碼示例
<1> 搭建服務器
1 class ServerStringTest { 2 3 main(){ 4 ServerSocket ss = null; 5 Socket s = null; 6 7 try{ 8 // 1.建立ServerSocket類型的對象,並提供端口號 9 ss = new ServerSocket(8888); 10 11 // 2.等待客戶端的鏈接請求,調用accept方法 12 while(true){ 13 println("等待客戶端的鏈接請求..."); 14 // 當沒有客戶端鏈接時,則,服務器阻塞在accept方法的調用處 15 s = ss.accept(); 16 println("客戶端" + s.getInetAddress() + "鏈接成功!"); 17 18 // 3.每當有一個客戶端鏈接成功,則須要啓動一個線程,爲之服務 19 new ServerThread(s).start(); // 見<2> 20 } 21 } catch (IOException e){ 22 e.printStackTrace(); 23 } finally { 24 // 4.關閉Socket,並釋放有關的資源 25 if(null != ss){ 26 try{ 27 ss.close(); 28 }catch(IOException e){ 29 e.printStackTrace(); 30 } 31 } 32 } 33 34 } 35 }
<2> 爲客戶端進行服務的線程
1 class ServerThread extends Thread { 2 3 private Socket s; 4 5 public ServerThread(Socket s){ 6 this.s = s; 7 } 8 9 @Override 10 public void run(){ 11 BufferedReader br = null; 12 PrintStream ps = null; 13 14 try{ 15 // 使用輸入輸出流進行通訊 16 br = new BufferedReader (new InputStreamReader(s.getInputStream()) ); 17 ps = new PrintStream(s.getOutputStream() ); 18 19 while(true){ 20 // 對客戶端發來字符串內容的接收,並打印 21 // 當沒有數據發來時,下面的方法會造成阻塞 22 String s1 = br.readLine(); 23 InetAddress inetAddress = s.getInetAddress(); 24 println("客戶端" + inetAddress + "發來的字符串內容是:" + s1); 25 // 當客戶端發來的內容爲"bye"時,則聊天結束 26 if("bye".equalsIgnoreCase(s1)){ 27 println("客戶端" + inetAddress + "已下線!"); 28 } 29 30 // 服務器向客戶端回發字符串內容 "I received!" 31 ps.println("I received!"); 32 println("服務器發送數據成功!") 33 } 34 } catch (IOException e){ 35 e.printStackTrace(); 36 } finally { 37 if (null != ps){ 38 ps.close(); 39 } 40 if (null != br) { 41 try { 42 br.close(); 43 } catch (IOException e) { 44 e.printStackTrace(); 45 } 46 } 47 if (null != s) { 48 try { 49 s.close(); 50 } catch (IOException e) { 51 e.printStackTrace(); 52 } 53 } 54 } 55 } 56 }
<3> 客戶端
1 class ClientStringTest { 2 main(){ 3 Socket s = null; 4 PrinterStream ps = null; 5 Scanner sc = null; 6 BufferedReader br = null; 7 8 try{ 9 // 1. 建立Socket類型的對象,並提供服務器的主機名和端口號 10 s = new Socket("127.0.0.1",8888); 11 println("鏈接服務器成功!"); 12 13 // 2. 使用輸入輸出流,進行通訊 14 sc = new Scanner(System.in); 15 ps = new PrinterStream(s.getOutputStream()); 16 br = new BufferedReader(new InputStreamReader(s.getInputStream())); 17 18 while(true){ 19 // Thread.sleep(10000); 20 // 實現客戶端發送的內容,由用戶從鍵盤輸入 21 println("請輸入要發送的數據內容:"); 22 String str1 = sc.next(); 23 24 // 實現客戶端向服務器發送字符串內容"hello" 25 // ps.println("hello"); 26 ps.println(str1); 27 println("客戶端發送數據內容成功!"); 28 29 // 當發送的數據內容爲"bye"時,則聊天結束 30 if ("bye".equalsIgnoreCase(str1) ){ 31 println("聊天結束!"); 32 break; 33 } 34 35 // 實現接收服務器發來的字符串內容,並打印 36 String str2 = br.readLine(); 37 println("服務器回發的消息是:" + str2); 38 } 39 } catch (IOException /*| InterruptedException*/ e) { 40 e.printStackTrace(); 41 } finally { 42 // 3.關閉Socket並釋放有關的資源 43 if (null != br) { 44 try { 45 br.close(); 46 } catch (IOException e) { 47 e.printStackTrace(); 48 } 49 } 50 if (null != ps) { 51 ps.close(); 52 } 53 if (null != sc) { 54 sc.close(); 55 } 56 if (null != s) { 57 try { 58 s.close(); 59 } catch (IOException e) { 60 e.printStackTrace(); 61 } 62 } 63 } 64 } 65 }