HTTP協(xié)議

項目要用到通信協(xié)議晚凿,強行學(xué)習(xí)了一波HTTP協(xié)議

報文格式

請求格式

HTTP請求由狀態(tài)行羽莺、請求頭笛匙、請求正文三部分組成:

  • 狀態(tài)行:包括請求方式Method班利、資源路徑URL饥漫、協(xié)議版本Version;
  • 請求頭:包括一些訪問的域名罗标、用戶代理庸队、Cookie等信息;
  • 請求正文:就是HTTP請求的數(shù)據(jù)闯割。

請求方式Method一般有GET彻消、POST、PUT宙拉、DELETE证膨,含義分別是獲取、修改鼓黔、上傳央勒、刪除,其中GET方式僅僅為獲取服務(wù)器資源澳化,方式較為簡單崔步,因此在請求方式為GET的HTTP請求數(shù)據(jù)中,請求正文部分可以省略缎谷,直接將想要獲取的資源添加到URL中井濒。


圖片.png
圖片.png

上面這張圖是Fiddle捕獲的一個實際請求報文灶似,它清晰的展示了HTTP 消息的結(jié)構(gòu)。詳情如下:

  • 請求行:即第一排用空格分割成的三個小塊瑞你,分別對應(yīng)請求方法酪惭、請求URL、HTTP協(xié)議版本三個部分者甲。
  • 請求頭:從第二行開始到倒數(shù)第二行都是我們的請求頭(headers)春感。
  • 消息主體:截圖的最后一行是請求體,也就是我們要發(fā)送的數(shù)據(jù)的主體虏缸,消息主體(entity-body)鲫懒。
  • 也就是說一個正常的post請求主要由請求行,請求頭刽辙,消息主體組成窥岩。接下來我們來了解一下什么是Content-Type。

Content-Type的格式種類

四種最常用的編碼方式宰缤,基本上形成了相應(yīng)的規(guī)范颂翼,即基本固定的Content-Type取值application/x-www-form-urlencoded(默認(rèn)格式)、application/json慨灭、text/xml朦乏、multipart/form-data,與默認(rèn)傳遞的urlencoded缘挑、json格式集歇、xml格式桶略、文件格式一 一對應(yīng)语淘。

應(yīng)答格式

HTTP響應(yīng)由三部分組成:狀態(tài)行、響應(yīng)頭际歼、響應(yīng)正文惶翻;

  • 狀態(tài)行:包括協(xié)議版本Version、狀態(tài)碼Status Code鹅心、回應(yīng)短語吕粗;
  • 響應(yīng)頭:包括搭建服務(wù)器的軟件,發(fā)送響應(yīng)的時間旭愧,回應(yīng)數(shù)據(jù)的格式等信息颅筋;
  • 響應(yīng)正文:就是響應(yīng)的具體數(shù)據(jù)


    圖片.png

使用輪子

Python Requests 快速上手
https://2.python-requests.org//zh_CN/latest/user/quickstart.html
Python實現(xiàn)簡單HTTP服務(wù)器
https://www.cnblogs.com/xinyangsdut/p/9099623.html
Python Http Post請求四種請求體的Python實現(xiàn)
https://www.cnblogs.com/Detector/p/9404391.html

使用socket創(chuàng)建簡單的客戶端和服務(wù)端

客戶端

client.py

# -*- coding: utf-8 -*-
"""
Created on Fri Jul  5 17:00:36 2019

@author: Administrator
"""

import socket 

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 連接服務(wù)端
s.connect(('127.0.0.1', 9999))

# 請求 | 發(fā)送數(shù)據(jù)到服務(wù)端
s.sendall(b'hello')

# 響應(yīng) | 接受服務(wù)端返回到數(shù)據(jù)
data = s.recv(1024)

print(data) # hello

# 關(guān)閉 socket
s.close()

服務(wù)端

# -*- coding: utf-8 -*-
"""
Spyder Editor

This is a temporary script file.
"""

import socket 

# socket.AF_INET (IPV4)
# socket.SOCK_STREAM (TCP)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 監(jiān)聽 IP:port
s.bind(('127.0.0.1', 9999))

# 最大允許連接數(shù)量
s.listen(3)

# 死循環(huán),重復(fù)的處理著每個客戶端的請求
while True:

# 阻塞 每當(dāng)有客戶端的請求過來開始執(zhí)行
# 連接處理 (已完成三次握手)并獲取資源對象 | conn 請求對象 | addr 客戶端地址 ip: port
conn, addr = s.accept() 

# 請求處理 | 讀取客戶端發(fā)送過來的數(shù)據(jù) | recv(1024) 指定每次讀取 1024 字節(jié)输枯,當(dāng)數(shù)據(jù)較長時可以通過 while 循環(huán)讀取
data = conn.recv(1024).decode('utf-8')

# 響應(yīng)處理 | 把客服端發(fā)送過來的數(shù)據(jù)又轉(zhuǎn)發(fā)回去
conn.sendall(data.encode('utf-8'))

# 關(guān)閉客戶端連接
conn.close()

HTTP服務(wù)端

# -*- coding: utf-8 -*-
"""
Created on Mon Jul  8 09:02:54 2019

@author: Administrator
"""

# coding:utf-8

import socket
import json

from multiprocessing import Process

def handle_client(client_socket):
    """
    處理客戶端請求
    """
    request_data = client_socket.recv(1024)
    print("request data:", request_data)
    # 構(gòu)造響應(yīng)數(shù)據(jù)
    response_start_line = "HTTP/1.1 200 OK\r\n"
    response_headers = "Server: My server\r\n"
    response_body = "<h1>Python HTTP Test</h1>"
    datas={"param1": "Detector", "param2": "cnblogs"}
    response = response_start_line + response_headers + "\r\n" + datas

    # 向客戶端返回響應(yīng)數(shù)據(jù)
    client_socket.send(bytes(response, "utf-8"))

    # 關(guān)閉客戶端連接
    client_socket.close()


if __name__ == "__main__":
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind(("", 8000))
    server_socket.listen(128)
    

    while True:
        client_socket, client_address = server_socket.accept()
        
        print("[%s, %s]用戶連接上了" % client_address)
        handle_client_process = Process(target=handle_client, args=(client_socket,))
        handle_client_process.start()
        client_socket.close()

C端TCP/IP 服務(wù)器

#include<iostream>
#include<winsock.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
void initialization();
int server() {
    //定義長度變量
    int send_len = 0;
    int recv_len = 0;
    int len = 0;
    //定義發(fā)送緩沖區(qū)和接受緩沖區(qū)
    char send_buf[100];
    char recv_buf[100];
    memset(send_buf, 0, sizeof(send_buf));
    memset(recv_buf, 0, sizeof(recv_buf));
    //定義服務(wù)端套接字议泵,接受請求套接字
    SOCKET s_server;
    SOCKET s_accept;
    //服務(wù)端地址客戶端地址
    SOCKADDR_IN server_addr;
    SOCKADDR_IN accept_addr;
    initialization();
    //填充服務(wù)端信息
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(8001);
    //創(chuàng)建套接字
    s_server = socket(AF_INET, SOCK_STREAM, 0);
    if (bind(s_server, (SOCKADDR *)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR) {
        cout << "bing faild!" << endl;
        WSACleanup();
    }
    else {
        cout << "bing success!" << endl;
    }
    //設(shè)置套接字為監(jiān)聽狀態(tài)
    if (listen(s_server, SOMAXCONN) < 0) {
        cout << "listen faild!" << endl;
        WSACleanup();
    }
    else {
        cout << "listen success!" << endl;
    }
    cout << "listening...." << endl;
    //接受連接請求
    len = sizeof(SOCKADDR);
    s_accept = accept(s_server, (SOCKADDR *)&accept_addr, &len);
    if (s_accept == SOCKET_ERROR) {
        cout << "listen faild!" << endl;
        WSACleanup();
        return 0;
    }
    cout << "connect..." << endl;
    //接收數(shù)據(jù)
    while (1) {
        recv_len = recv(s_accept, recv_buf, 1, 0);
        if (recv_len <= 0) {
            cout << "rec failed!" << endl;
            break;
        }
        else {
            cout << "client:" << recv_buf << endl;
        }
        /*cout << "please cin:";
        cin >> send_buf;*/
        //send_len = send(s_accept, send_buf, 100, 0);
        //if (send_len < 0) {
        //  cout << "send failed!" << endl;
        //  break;
        //}
    }
    //關(guān)閉套接字
    closesocket(s_server);
    closesocket(s_accept);
    //釋放DLL資源
    WSACleanup();
    return 0;
}

void initialization() {
    //初始化套接字庫
    WORD w_req = MAKEWORD(2, 2);//版本號
    WSADATA wsadata;
    int err;
    err = WSAStartup(w_req, &wsadata);
    if (err != 0) {
        cout << "init faied!" << endl;
    }
    else {
        cout << "init success!" << endl;
    }
    //檢測版本號
    if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wHighVersion) != 2) {
        cout << "version error!" << endl;
        WSACleanup();
    }
    else {
        cout << "version right!" << endl;
    }
    //填充服務(wù)端地址信息

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市桃熄,隨后出現(xiàn)的幾起案子先口,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件碉京,死亡現(xiàn)場離奇詭異厢汹,居然都是意外死亡,警方通過查閱死者的電腦和手機谐宙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進(jìn)店門烫葬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人卧惜,你說我怎么就攤上這事厘灼。” “怎么了咽瓷?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵设凹,是天一觀的道長。 經(jīng)常有香客問我茅姜,道長闪朱,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任钻洒,我火速辦了婚禮奋姿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘素标。我一直安慰自己称诗,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布头遭。 她就那樣靜靜地躺著寓免,像睡著了一般。 火紅的嫁衣襯著肌膚如雪计维。 梳的紋絲不亂的頭發(fā)上袜香,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天,我揣著相機與錄音鲫惶,去河邊找鬼蜈首。 笑死,一個胖子當(dāng)著我的面吹牛欠母,可吹牛的內(nèi)容都是我干的欢策。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼赏淌,長吁一口氣:“原來是場噩夢啊……” “哼踩寇!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起猜敢,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤姑荷,失蹤者是張志新(化名)和其女友劉穎盒延,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鼠冕,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡添寺,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了懈费。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片计露。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖憎乙,靈堂內(nèi)的尸體忽然破棺而出票罐,到底是詐尸還是另有隱情,我是刑警寧澤泞边,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布该押,位于F島的核電站,受9級特大地震影響阵谚,放射性物質(zhì)發(fā)生泄漏蚕礼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一梢什、第九天 我趴在偏房一處隱蔽的房頂上張望奠蹬。 院中可真熱鬧,春花似錦嗡午、人聲如沸囤躁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽狸演。三九已至,卻和暖如春应媚,著一層夾襖步出監(jiān)牢的瞬間严沥,已是汗流浹背猜极。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工中姜, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人跟伏。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓丢胚,卻偏偏與公主長得像,于是被迫代替她去往敵國和親受扳。 傳聞我的和親對象是個殘疾皇子携龟,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,941評論 2 355

推薦閱讀更多精彩內(nèi)容