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地址**能夠惟一標識網絡中的設備,那麼**端口號**就能夠惟一標識設備中的進程(應用程序)了。

- **端口號:用兩個字節表示的整數,它的取值範圍是0~65535**。其中,0~1023之間的端口號用於一些知名的網絡服務和應用,普通的應用程序須要使用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();
    }}

##總結
    這只是一個最簡單的列子,也沒有寫服務器回寫數據,作本身太懶,不想寫了,若是文中有什麼問題歡迎指正



java

相關文章
相關標籤/搜索