日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

网络——实现服务器

發布時間:2023/12/3 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 网络——实现服务器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【0】README

0.1) 本文描述部分轉自 core java volume 2 , 旨在理解 網絡——實現服務器 的基礎知識 ;
0.2) for source code, please visit https://github.com/pacosonTang/core-java-volume/blob/master/coreJavaAdvanced/chapter3/EchoServer.java + https://github.com/pacosonTang/core-java-volume/blob/master/coreJavaAdvanced/chapter3/ThreadedEchoServer.java


【1】實現服務器

1)看個荔枝:我們的服務器可以向client 發送信息;
2)服務器描述:

  • 2.1)一旦啟動服務器程序, 它便等待某個客戶端連接到他的端口;
  • 2.2)ServerSocket 類用于建立服務器套結字, 如:
ServerSocket s = new ServerSocket(8189)
  • 2.3)用于建立一個監控8189的服務器,如:
Socket incoming = s.accept();
  • 2.4)上述代碼用于告訴程序不停地等待, 直到有client就連接到這個端口;
  • 2.5)如果有client 連接到 server 的 8189端口, 可以使用這個對象來得到輸入流和輸出流, 如:
InputStream inStream = incoming.getInputStream(); OutputStream outStream = incoming.getOutputStream();
  • 2.6)服務器發送給服務器輸出流的所有信息都會成為 client 程序的輸入, 同時來自 client 程序的所有輸出都會被包含在 服務器輸入流中;
  • 2.7)因為本章中的程序,我們都要通過套接字來發送文本, 所以我們將流轉換為掃描器和寫入器:
InputStream inStream = incoming.getInputStream(); OutputStream outStream = incoming.getOutputStream(); try (Scanner in = new Scanner(inStream)) PrintWriter out = new PrintWriter(outStream, true /* autoFlush */);
  • 2.8)以下代碼將給client 發送一條信息:
out.println("hello, ");
  • 2.9)代碼最后,我們關閉了連接進來的套接字:
incoming.close();
  • Conclusion) 這就是大致情況。 每一個server 程序, 比如一個 HTTP web 服務器, 都不間斷地執行這個循環:

    • C1)通過輸入數據流從客戶端接收一個命令;
    • C2)解碼這個客戶端命令;
    • C3) 收集客戶端所請求的信息;
    • C4) 通過輸出數據流發送消息給客戶端;


【2】為多個客戶端服務(有多個client 同時連接到我們的server上)

1)假設我們希望有多個客戶端同時連接到我們的server上, 每當程序建立一個新的套接字連接, 即當調用accept 時, 將啟動一個新線程來處理服務器和該客戶端間的連接, 而主程序將立即返回并等待下一個連接;
2)為了實現這個機制, 服務器應該具有以下代碼的循環操作:

while (true){ Socket incoming = s.accept();System.out.println("Spawning " + i);Runnable r = new ThreadedEchoHandler(incoming);Thread t = new Thread(r);t.start();i++;}
  • 2.1)ThreadEchoHandler 類實現了 Runnable接口,而在它的run方法中包含了與client 循環通信的代碼:
public void run(){ try{ try{InputStream inStream = incoming.getInputStream();OutputStream outStream = incoming.getOutputStream(); Scanner in = new Scanner(inStream); PrintWriter out = new PrintWriter(outStream, true /* autoFlush */); out.println( "Hello! Enter BYE to exit." ); // echo client inputboolean done = false;while (!done && in.hasNextLine()){ String line = in.nextLine(); out.println("Echo: " + line); if (line.trim().equals("BYE"))done = true;}}finally{incoming.close();}}catch (IOException e){ e.printStackTrace();}}
  • 2.2)由于每一個連接都會啟動一個新的線程,因而多個client 就可以同時連接到 server了;

3)看個荔枝(做個測試):

  • step1)編譯和運行服務器程序;
  • step2)打開 數個 telnet 窗口;
  • step3)切換窗口,鍵入命令(telnet localhost(or your visitorial host) port )。注意你可以同時通過這些窗口進行通信;
  • step4) 完成之后,切換到你啟動服務器的窗口, 使用ctrl +c 強制關閉它;



【3】半關閉

1)引入半關閉的原因: 半關閉提供了這樣一種能力: 套接字連接的一端可以終止其輸出,同時仍舊可以接收來自另一端的數據;
2)problem+solution

  • 2.1)problem: 這是一種很典型的case。 例如,我們在向服務器傳輸數據, 但是并不知道要傳輸多少數據。在向文件寫數據時,我們只需在數據寫入后關閉文件即可。 但是,如果關閉一個套接字,那么與服務器的連接將立即斷開, 因而也就無法讀取服務器的響應了;
  • 2.2)solution:使用半關閉就可以解決。 可以通過關閉一個套接字的輸出流來表示發送給服務器的請求數據已經結束, 但是必須保持輸入流處于打開狀態;

3)以下代碼演示了 如何在客戶端使用半關閉方法:

Socket socket = new Socket(host, port); Scanner in = new Scanner(socket.getInputStream() ); PrintWriter writer = new PrintWriter(socket.getOutputStream()); writer.print(...); writer.flush(); socket.shutdownOutput(); // client 關閉 outputStream,但是保持inputStream 處于開啟狀態; while(in.hasNextLine() != null) {String line = in.nextLine();...... } socket.close();
  • 3.1)服務器端將讀取輸入信息,直到到達輸入流的結尾, 然后它再發送響應; 然后上述代碼中的while 循環讀取 server 的response info;
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的网络——实现服务器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。