1. 程式人生 > 其它 >shell 指令碼如何判斷檔案是否存在

shell 指令碼如何判斷檔案是否存在

  HTTP協議(Hypertext Transfer Protocol,超文字傳輸協議),顧名思義,是關於如何在網路上傳輸超文字(即HTML文件)的協議。HTTP協議規定了Web的基本運作過程,以及瀏覽器與Web伺服器之間的通訊細節。HTTP協議採用客戶/伺服器通訊模式, 是目前在Internet上應用最廣泛的通訊協議之一

  如圖所示,在分層的網路體系結構中,HTTP協議位於應用層,建立在TCP/IP協議的基礎上。HTTP協議使用可靠的TCP連線,預設埠是80埠

  HTTP協議規定Web的基本運作過程基於客戶/伺服器通訊模式,客戶端主動發出HTTP請求,服務端接收HTTP請求,再返回相應的HTTP響應結果。客戶端與伺服器之間的一次資訊交換包括以下過程:

    (1)客戶端與伺服器端建立TCP連線

    (2)客戶端發出HTTP請求。

    (3)伺服器端發出相應的HTTP響應

    (4)客戶端與伺服器端之間的TCP連線關閉

           HTTP協議規定的資訊交換過程

HTTP協議特點

基於 請求-響應 的模式

  HTTP協議規定,請求從客戶端發出,最後伺服器端響應該請求並返回。換句話說,肯定是先從客戶端開始建立通訊的,伺服器端在沒有接收到請求之前不會發送響應。從瀏覽器與Web伺服器的通訊過程中,可以看出瀏覽器應該具備以下功能:

  • 請求與Web伺服器建立TCP連線
  • 建立併發送HTTP請求
  • 接收並解析HTTP響應
  • 在視窗中展示HTML文件

  Web伺服器應該具備以下功能:

  • 接收來自瀏覽器的HTTP請求
  • 接收並解析HTTP請求
  • 建立併發送HTTP響應

  Http客戶程式和Http伺服器分別由不同的軟體開發商提供,目前最常用的HTTP客戶程式包括IE、Chrome、Firefox、Opera和Netscape等,最常用的HTTP伺服器包括IIS和Apache等。

無狀態儲存

  HTTP是一種不儲存狀態,即無狀態(stateless)協議。HTTP協議自身不對請求和響應之間的通訊狀態進行儲存。也就是說在HTTP這個級別,協議對於傳送過的請求或響應都不做持久化處理。使用HTTP協議,每當有新的請求傳送時,就會有對應的新響應產 生。協議本身並不保留之前一切的請求或響應報文的資訊。這是為了更快地處理大量事務,確保協議的可伸縮性,而特意把HTTP協議設計成 如此簡單的。

無連線

  無連線的含義是限制每次連線只處理一個請求。伺服器處理完客戶的請求,並收到客戶的應答後,即斷開連線。採用這種方式可以節省傳輸時間,並且可以提高併發效能,不能和每個使用者建立長久的連線,請求一次相應一次,服務端和客戶端就中斷了。但是無連線有兩種方式,早期的http協議是一個請求一個響應之後,直接就斷開了,但是現在的http協議1.1版本不是直接就斷開了,而是等幾秒鐘,這幾秒鐘是等什麼呢,等著使用者有後續的操作,如果使用者在這幾秒鐘之內有新的請求,那麼還是通過之前的連線通道來收發訊息,如果過了這幾秒鐘使用者沒有傳送新的請求,那麼就會斷開連線,這樣可以提高效率,減少短時間內建立連線的次數,因為建立連線也是耗時的

簡單快速

  客戶向伺服器請求服務時,只需傳送請求方法和路徑。請求方法常用的有GET、HEAD、POST、PUT、DELETE、TRACE、OPTIONS。每種方法規定了客戶與伺服器聯絡的型別不同。     由於HTTP協議簡單,使得HTTP伺服器的程式規模小,因而通訊速度很快。 

  其中get與post請求方式最常用

  get與post請求區別

  • GET提交的資料會放在URL之後,也就是請求行裡面,以?分割URL和傳輸資料,引數之間以&相連,如EditBook?name=test1&id=123456.(請求頭裡面那個content-type做的這種引數形式,後面講) POST方法是把提交的資料放在HTTP包的請求體中.

  • GET提交的資料大小有限制(因為瀏覽器對URL的長度有限制),而POST方法提交的資料沒有限制.

  • GET與POST請求在服務端獲取請求資料方式不同,就是我們自己在服務端取請求資料的時候的方式不同了

靈活

  HTTP允許傳輸任意型別的資料物件。正在傳輸的型別由Content-Type加以標記【MIME】    

請求頭

  請求頭包含許多有關客戶端環境和請求正文的有用資訊。例如:瀏覽器的型別、所用的語言、請求正文的型別,以及請求正文的長度等

  請求頭和請求正文之間必須以空行分割。

 

響應頭

  由三部分構成(HTTP協議的版本、狀態碼和描述;響應頭;響應正文)

狀態碼解釋
1×× 保留

2×× 表示請求成功地接收

3×× 為完成請求客戶需進一步細化請求

4×× 客戶錯誤(404,405)

5×× 伺服器錯誤

用java套接字建立HTTP客戶與伺服器程式

package edu.uestc.avatar;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Executors;

public class HttpServer {
    public static void main(String[] args) throws IOException, InterruptedException {
        int port = 8080;
        try(var server = new ServerSocket(port)){
            System.out.println("伺服器正在監聽埠:" + server.getLocalPort());
            var executor = Executors.newCachedThreadPool();
            while(true) {
                var socket = server.accept();
                executor.execute(new Thread(()->{
                    try {
                        service(socket);
                    } catch (IOException | InterruptedException e) {
                        e.printStackTrace();
                    }
                }));
            }
        }
        
    }
    
    public static void service(Socket socket) throws IOException, InterruptedException {
        var input = socket.getInputStream();
        Thread.sleep(500);//休眠500毫秒,等待http請求
        var size = input.available();
        var buffer = new byte[size];
        input.read(buffer);
        var request = new String(buffer);
        System.out.println(request);
        
        /*
         * 解析http請求
         */
        //獲取http請求的第一行
        var line1 = request.substring(0, request.indexOf("HTTP/1.1"));
        //獲取url資訊
        var url = line1.split(" ")[1];
        
        /*
         * http響應
         */
        var contentType = ""; //響應的文件型別
        var suffix = url.substring(url.lastIndexOf(".") + 1);
        if("html".equals(suffix) || "htm".equals(suffix))
            contentType = "text/html; charset=utf-8";
        else if("gif".equals(suffix))
            contentType = "image/gif";
        else if("jpg".equals(suffix) || "jpej".equals(suffix))
            contentType = "image/jpeg";
        else
            contentType = "application/octet-stream";
        
        var responseResult = "HTTP/1.1 200 OK\r\n";
        //響應頭和響應內容中間有一個空行
        var responseHeader = "Content-Type:" + contentType + "\r\n\r\n";
        
        //定義伺服器的根路徑
        var root = "public";
        var resourceInput = new BufferedInputStream(new FileInputStream(root + url));
        
        var out = socket.getOutputStream();
        out.write(responseResult.getBytes());
        out.write(responseHeader.getBytes());
        
        var len = -1;
        var buff = new byte[1024];
        while((len = resourceInput.read(buff)) != -1) {
            out.write(buff, 0, len);
        }
        socket.close();
        resourceInput.close();
    }
}