Java模擬實現B/S服務器

Java模擬實現B/S服務器

軟件結構

C/S結構:全稱CLient/Server結構,是客戶端/服務器結構,常見的這一類軟件有QQ,電腦,以及電腦上的一系列客戶端軟件

B/S結構:全稱Browser/Server結構,是瀏覽器/服務器結構,就是我們經常利用瀏覽器進行訪問,常見的有chrome,Firefox,IE等等。

網絡通信協議

網絡通信協議:計算機與計算機或者說通信設備之間通過線路或者無線網絡連接,但不是說連接起來就能通信,還必須要遵守一定的規矩,也就是協議,就好像現實社會中你有了車就能隨心所欲的開嗎?顯然是不可以的你還得遵守交通法規,不然交警叔叔分分鐘給你貼罰單,題外話。在計算機網絡中,這樣的一些連接和 通信的規則被稱爲網絡通信協議,它對數據的傳輸格式、傳輸速率、傳輸步驟等做了統一規定,通信雙方必須同時遵守才能完成數據交換。

TCP/IP協議:傳輸控制協議/因特網互聯協議( Transmission Control Protocol/Internet Protocol),是Internet最基本、最廣泛的協議。它定義了計算機如何連入因特網,以及數據如何在它們之間傳輸的標準。它的內部包含一系列的用於處理數據通信的協議,並採用了4層的分層模型,每一層都呼叫它的下一層所提供的協議來完成自己的需求。

TCP/IP協議分爲四層,自己本身也對這方面不熟悉,寫軟件的其實就是和第四層打交道,也就是應用層,主要負責應用程序的協議,例如HTTP協議、FTP協議等。

協議分類

通信的協議還是比較複雜的,java.net 包中包含的類和接口,它們提供低層次的通信細節。我們可以直接使用這些類和接口,來專注於網絡程序開發,而不用考慮通信的細節。其實這也是面向對象的一大好處,當然了也是以達壞處,好處在於你不用去考慮通信的細節,只需要調用對應的API就可以了,壞處就是大多數人對底層的認知不夠,其實這是相當可怕的一件事,多瞭解一些底層的實現原理其實是在爲自己以後的職業生涯拓寬道路。

java.net 包中提供了兩種常見的網絡協議的支持:

UDP:用戶數據報協議(User Datagram Protocol)。UDP是無連接通信協議,即在數據傳輸時,數據的發送端和接收端不建立邏輯連接。簡單來說,當一臺計算機向另外一臺計算機發送數據時,發送端不會確認接收端是否存在,就會發出數據,同樣接收端在收到數據時,也不會向發送端反饋是否收到數據。

由於使用UDP協議消耗資源小,通信效率高,所以通常都會用於音頻、視頻和普通數據的傳輸例如視頻會議都使用UDP協議,因爲這種情況即使偶爾丟失一兩個數據包,也不會對接收結果產生太大影響。

但是在使用UDP協議傳送數據時,由於UDP的面向無連接性,不能保證數據的完整性,因此在傳輸重要數據時不建議使用UDP協議。UDP的交換過程如下圖所示。

特點:數據被限制在64kb以內,超出這個範圍就不能發送了。

數據報(Datagram):網絡傳輸的基本單位

TCP:傳輸控制協議 (Transmission Control Protocol)。TCP協議是面向連接的通信協議,即傳輸數據之前,在發送端和接收端建立邏輯連接,然後再傳輸數據,它提供了兩臺計算機之間可靠無差錯的數據傳輸。

在TCP連接中必須要明確客戶端與服務器端,由客戶端向服務端發出連接請求,每次連接的創建都需要經過“三次握手”。

  • 三次握手:TCP協議中,在發送數據的準備階段,客戶端與服務器之間的三次交互,以保證連接的可靠。
    • 第一次握手,客戶端向服務器端發出連接請求,等待服務器確認。
    • 第二次握手,服務器端向客戶端回送一個響應,通知客戶端收到了連接請求。
    • 第三次握手,客戶端再次向服務器端發送確認信息,確認連接。整個交互過程.

完成三次握手,連接建立後,客戶端和服務器就可以開始進行數據傳輸了。由於這種面向連接的特性,TCP協議可以保證傳輸數據的安全,所以應用十分廣泛,例如下載文件、瀏覽網頁等。

網絡編程三要素

協議

  • 計算機網絡通信必須遵守的規則,這方面其實是很複雜的,有興趣的朋友可以自己下去單獨找一些這方面的書籍瞭解一下。

IP地址

  • IP地址:指互聯網協議地址(Internet Protocol Address),俗稱IP。IP地址用來給一個網絡中的計算機設備做唯一的編號。假如我們把“個人電腦”比作“一臺電話”的話,那麼“IP地址”就相當於“電話號碼”。

IP地址分類

  • IPv4:是一個32位的二進制數,通常被分爲4個字節,表示成a.b.c.d 的形式,例如192.168.65.100 。其中a、b、c、d都是0~255之間的十進制整數,那麼最多可以表示42億個。聲明一下,老美髮明的好像是,全世界一半以上的都被美國人留給了自己,咱們國內其實早都不夠用了。用了個什麼技術解決的記不清了,大學老師提過。

  • IPv6:由於互聯網的蓬勃發展,IP地址的需求量愈來愈大,但是網絡地址資源有限,使得IP的分配越發緊張。

    爲了擴大地址空間,擬通過IPv6重新定義地址空間,採用128位地址長度,每16個字節一組,分成8組十六進制數,表示成ABCD:EF01:2345:6789:ABCD:EF01:2345:6789,號稱可以爲全世界的每一粒沙子編上一個網址,這樣就解決了網絡地址資源數量不夠的問題。主要的研發者是咱們中國,研究水平居於世界一流,美國人對這部研究不是很有興趣,應爲IPv4認加夠用了

端口號

網絡的通信,本質上是兩個進程(應用程序)的通信。每臺計算機都有很多的進程,那麼在網絡通信時,如何區分這些進程呢?

如果說IP地址可以唯一標識網絡中的設備,那麼端口號就可以唯一標識設備中的進程(應用程序)了。

  • **端口號:用兩個字節表示的整數,它的取值範圍是065535**。其中,01023之間的端口號用於一些知名的網絡服務和應用,普通的應用程序需要使用1024以上的端口號。如果端口號被另外一個服務或應用所佔用,會導致當前程序啓動失敗。

利用協議+IP地址+端口號 三元組合,就可以標識網絡中的進程了,那麼進程間的通信就可以利用這個標識與其它進程進行交互。也就是說利用IP地址找到對方的通信設備,利用端口號找到要通信的進程,如果沒有端口號那你用微信給朋友發送一條信息對方用QQ接收到了,那感覺絕對挺爽的。

TCP通信程序

概述

TCP通信能實現兩臺計算機之間的數據交互,通信的兩端,要嚴格區分爲客戶端(Client)與服務端(Server)。

兩端通信時步驟:

  1. 服務端程序,需要事先啓動,等待客戶端的連接。
  2. 客戶端主動連接服務器端,連接成功才能通信。服務端不可以主動連接客戶端。

在Java中,提供了兩個類用於實現TCP通信程序:

  1. 客戶端:java.net.Socket 類表示。創建Socket對象,向服務端發出連接請求,服務端響應請求,兩者建立連接開始通信。
  2. 服務端:java.net.ServerSocket 類表示。創建ServerSocket對象,相當於開啓一個服務,並等待客戶端的連接。

Socket類

Socket 類:該類實現客戶端套接字,套接字指的是兩臺設備之間通訊的端點。

構造方法

  • public Socket(String host, int port) :創建套接字對象並將其連接到指定主機上的指定端口號。如果指定的host是null ,則相當於指定地址爲回送地址。

小貼士:回送地址(127.x.x.x) 是本機回送地址(Loopback Address),主要用於網絡軟件測試以及本地機進程間通信,無論什麼程序,一旦使用回送地址發送數據,立即返回,不進行任何網絡傳輸。

ServerSocket類

ServerSocket類:這個類實現了服務器套接字,該對象等待通過網絡的請求。

構造方法

  • public ServerSocket(int port) :使用該構造方法在創建ServerSocket對象時,就可以將其綁定到一個指定的端口號上,參數port就是端口號。

簡單的TCP網絡程序

TCP通信分析圖解

  1. 【服務端】啓動,創建ServerSocket對象,等待連接。
  2. 【客戶端】啓動,創建Socket對象,請求連接。
  3. 【服務端】接收連接,調用accept方法,並返回一個Socket對象。
  4. 【客戶端】Socket對象,獲取OutputStream,向服務端寫出數據。
  5. 【服務端】Scoket對象,獲取InputStream,讀取客戶端發送的數據。

到此,客戶端向服務端發送數據成功。

模擬實現B/S服務器

##服務端實現

public class ServerTCP {
    public static void main(String[] args) throws IOException {
        //建立服務器,並監聽8888端口
        ServerSocket server = new ServerSocket(8888);
        //監聽客戶端
        Socket accept = server.accept();
        //通過socket獲取輸入流
        InputStream inputStream = accept.getInputStream();
        //讀取數據
        int len;
        byte[] bytes = new byte[1024];
        while ((len = inputStream.read(bytes)) != -1) {
            System.out.println(new String(bytes,0,len));
        }
        
        inputStream.close();
        server.close();
    }
  }

##客戶端實現

 public class ClientTest {
    public static void main(String[] args) throws IOException{
        //創建客戶端
        Socket socket = new Socket("127.0.0.1",8888);
        //通過socket獲取字節輸出流
        OutputStream outputStream = socket.getOutputStream();
        //寫出數據,將數據發送到服務端
        Scanner sc = new Scanner(System.in);
        outputStream.write(sc.nextLine().getBytes());
        outputStream.close();
    }
  }

總結

這只是一個最簡單的列子,也沒有寫服務器回寫數據,自己太懶,各位看官見諒,寫博文的目的只是爲了記錄自己的新得體會

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章