tcp/ip協議
- 定義:利用 IP 進行通信時所必須用到的協議群的統稱。具體來說,IP 或 ICMP、TCP 或 UDP、TELNET 或 FTP、以及 HTTP 等都屬於 TCP/IP 議。
- OSI 七層模型:物理層、數據鏈路層、網絡層、傳輸層、會話層、表示層、應用層。
- TCP/IP 四層模型:應用層(http協議)、傳輸層(tcp協議、端口)、網絡層(本機和服務器的ip地址)、數據鏈路層(本機和路由器的mac地址)
- 區別: https://blog.csdn.net/namechenfl/article/details/90767551
- mac地址:硬件地址,識別同一鏈路中不同的計算機,網卡出廠設定,具有唯一性(osi數據鏈路層)
- ip地址:來識別 TCP/IP 網絡中互連的主機和路由器,分為私有ip、公有ip,(osi網絡層)
- 端口號:識別同一台計算機中進行通信的不同應用程序
三次握手
意義:確認客戶端和服務端雙方都可以正常發送、接收請求
http協議之前的三個tcp包即為三次握手的過程。
source 發送機ip destination 接收機ip
由上可見 :
- 本機向百度發送一個tcp包,此時 seq=0;服務器知道:自己接收正常、客戶端發送正常
- 百度向本機發送了一個tcp包,seq=0 ack=1;客戶端知道:自己發送正常、接收正常,服務器接收正常、發送正常
- 本機向百度發送一個tcp包,seq=1 ack=1;服務器知道:自己發送正常,客戶端接收正常
- 客戶端、服務器知道自己和對方都發送、接收正常,完成三次握手,開始進行http請求。
四次揮手
- 客戶端發送FIN,seq請求斷開,表示不會再發送請求,但可以接收請求;
- 服務器接收到斷開請求,確認斷開;
- 服務器請求斷開;
- 客戶端收到斷開請求,確認斷開。
tcp協議分析
-
下載安裝wireshark, https://www.wireshark.org/download.html/
-
下載WinDump, http://www.winpcap.org/windump/
-
將WinDump放到一個合適的目錄,加入環境變量
-
打開終端,開啟windump 網絡監聽
WinDump.exe -i 3 -Al -v -w /e/otherCode/1.txt host www.baidu.com # -i 監聽指定的接口(網卡接口?),如果不指定,自動匹配數值最小的接口,比如我電腦有3個網卡,不指定的情況下,默認為-i 1 # -A 以ASCII格式打印每個數據包(減去其鏈接級別標題)。 方便捕獲網頁。格式化輸出。 # -l 使標准輸出行緩存,如果要在捕獲數據時查看數據,則很有用 # -w 將捕獲的數據包寫入文件中,而不打印出來
-
再打開一個終端窗口,使用 curl發包
curl http://www.baidu.com
-
使用wireshark打開1.txt
curl命令發包
curl -G url https://www.baidu.com --data-urlencod "wd:python" -H 'Connection: keep-alive' -H 'Cache-Control: max-age=0' -H 'Upgrade-Insecure-Requests: 1' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8' -H 'Cookie: BAIDUID=5403DAC6AEC8B48DCC6A3D45552B9CD6:FG=1; BIDUPSID=5403DAC6AEC8B48DCC6A3D45552B9CD6; PSTM=1568602233; BDUSS=BrMX5HN2l5NmtFLWdhU3ZHYThHakY3cm94UUZlR3l-TTU1My1leWpmNHJkS2hkRVFBQUFBJCQAAAAAAAAAAAEAAAD6VgShbmljZcLt6LQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvngF0r54BdRj; _homeland_session=lIG%2F9zPjSHHWta%2BKXwOOry%2FOxa3NGGyPzoE0Eek8rAel8wmq4FAv0Sa1PQhR1I5MNTpopx3zCJeLykMFt6xGjAB66RZ5hhJOKMXEdIpbORyYYIENsEyciBeNCYkz7IKVAKWdhvF4NzH1BFxhHc35ONOm59%2F8%2FRJ0nfj4tXD97PoiS02Zpe4WDtZTZrg%2Fmm5BN%2BOnn0qHFA%2BmkndNQOLhIyLT3Tt8nVki0cg74IV5Mzo%2FSE28u2HS9IdkoiagIllYZehGJwiMDN7UH%2Fwc1jFc%2BJMp94Alu%2Fnxrg%3D%3D--8vazfTOh2Djn3G5e--f7J5EgYyZpIiw4UZYmtpOw%3D%3D; BD_UPN=123253; delPer=0; BD_CK_SAM=1; PSINO=2; H_PS_PSSID=1421_31170_21118_31187_30905_31051_30823_31085_26350; H_PS_645EC=ddce%2FJvbox9oZltdQxsz83h1tOXe35N1k0%2BsPVHJ9oX56aUNa87qp6eTeMSvp0CPlD5f; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BDRCVFR[feWj1Vr5u3D]=I67x6TjHwwYf0; BDSVRTM=168' --compressed
可從谷歌瀏覽器開發者工具network中右鍵請求來copy curl命令
常用參數
- s 靜默輸出
- G 將參數攜帶在url里邊
- –data-urlencod 將參數進行編碼
- o 將輸出內容保存到本地
- v 打印詳細發送的日志
- d 發送post請求時,攜帶的數據體
具體:https://www.ruanyifeng.com/blog/2019/09/curl-reference.html
nc/telnet
功能:發socket級別的數據包,看到請求過程,二者功能相同,telnet適用於windows。
用法:
nc www.baidu.com 80 -v
GET / HTTP/1.0
HOST:www.baidu.com
簡單練習
# 1.用curl發送一個header中攜帶user-agent:xxx的頭信息
curl -I -H 'User-Agent:hogwarts-ashin' 'http://www.baidu.com' -v
# 2.向雪球發起一個股票搜索
curl -G 'https://xueqiu.com/stock/search.json' --data-urlencode "code=阿里巴巴" --data-urlencode "size=3" --data-urlencode "page=1" -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36' -H 'elastic-apm-traceparent: 00-d874fd37925fbeab5e4f84e2f32a682e-444a22d0ee0952ed-01' -H 'Accept: application/json, text/plain, */*' -H 'Referer: https://xueqiu.com/k?q=%E9%98%BF%E9%87%8C%E5%B7%B4%E5%B7%B4' -H 'Cookie: device_id=24700f9f1986800ab4fcc880530dd0ed; _ga=GA1.2.889686388.1571316755; s=ci11rec8p6; acw_tc=2760824815851901643843314e96343459c7d769337f5e8d44cfcfc1bfb32e; aliyungf_tc=AQAAACTAEkRpQwEA0bjHb59FkyABvGUT; xq_a_token=2ee68b782d6ac072e2a24d81406dd950aacaebe3; xqat=2ee68b782d6ac072e2a24d81406dd950aacaebe3; xq_r_token=f9a2c4e43ce1340d624c8b28e3634941c48f1052; xq_id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1aWQiOi0xLCJpc3MiOiJ1YyIsImV4cCI6MTU4NzUyMjY2MSwiY3RtIjoxNTg1NDYxOTE5MDEwLCJjaWQiOiJkOWQwbjRBWnVwIn0.Gt45VHJaeY5YdyAZDXdB4LLE88Dco1NkBKlpcSBcmqTgiddsBF6TkeqikpBylRIX-HnzRJbtRpXKipoKW3INUBhDGQoq20B5GB_W9AVUyRZtIxHUl_BTfYyBGx5kB_odiODC7c9kk6W1Ctgx5pHj-CB8unMghl_pypvHxH7i8ONqAaSAGDDqq9q0T04UlGTocjd-UTIV9sHzLR76xd2vbUpyIQ1tK9igPyyV3anP7r7qbPqMrvKf772kucHU4mA9_U770xpvHSebFyHckjuv-vY_v1nAq6RUClZCODUdcKyGq089I-CTqPwlos5ImWHMFT8PRUvRwHxGiEPNNw5lqA; u=611585461963094; Hm_lvt_1db88642e346389874251b5a1eded6e3=1585190122,1585461920; Hm_lpvt_1db88642e346389874251b5a1eded6e3=1585461944' -H 'Connection: keep-alive' --compressed -v |jq
get與post
一個簡單的flask服務:
from flask import Flask, session, request, Request, make_response
app = Flask(__name__)
request: Request
app.secret_key = "key"
@app.route("/request", methods=['POST', 'GET'])
def hello():
query = request.args
post = request.form
return f"query: {query}\n" \
f"post: {post}"
@app.route("/session")
def session_handle():
for k, v in request.args.items():
session[k] = v
resp = make_response({k: v for k, v in session.items()})
for k, v in request.args.items():
resp.set_cookie(f"cookie_{k}", v)
return resp
# windows終端運行,其它終端將set替換為export
# set FLASK_APP=demo.py
# flask run
部署好之后可以在本機發送請求
curl -s 'http://127.0.0.1:5000/request?a=1&b=2' -v &> /e/otherCode/get
curl -s 'http://127.0.0.1:5000/request?a=1&b=2' -d 'c=3&d=4' -v &> /e/otherCode/post
# 在pycharm中選中這兩個文件,右擊compare Files 打開,可對比
首先明白兩個個概念:
- query,請求參數,一般指url中?后面跟的參數;
- ImmutableMultiDicts,flask框架中的一種數據類型,列表;
由上圖對比可見,共有7處不同,說3處關鍵的:
- 第2行,get請求的post ImmutableMultiDicts 沒有數據,post請求有;
- 第4行,請求method不同,一個是get,一個是post;
- 第13行,Content-Lenght和Content-Type不同,post請求有(form、json、xml、binary等格式),get沒有;
其他方面:
- 無狀態變化的請求一般用get,例如查詢;
- 有數據寫入、修改等狀態的建議用post,例如注冊、新增;
cookie、session、token
- 保持http連接的東西,session在服務端,cookie在客戶端
- cookie:用戶登錄后,瀏覽器會接受服務器的set-cookie指令,並把cookie保存到電腦上。用戶之后的請求會攜帶cookie,相當於攜帶一個登陸信息,從而避免重復輸入用戶名密碼;注意,安卓原生不支持cookie,這時的session可放在query或header中
- session:即會話控制,需要配合cookie使用,cookie中有一個session標識,請求過去之后,如果服務器有對應的session標識,就使用當前的session。簡單來講:session數據存儲到服務端,只把關聯數據的一個加密串放到cookie中標記,請求時驗證;
- token:也是登錄后服務器返回的一串數據,之后請求時攜帶,通常用於驗證用戶身份與權限,一般攜帶在query中;
關於過期時間:
- cookie:兩種,一是關閉瀏覽器自動過期;一是設置好過期時間,到點過期;
- session:發呆時間,用戶不操作 ** 時間后自動失效;
- token:靈活設置,可發呆,可固定,可持續。