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:灵活设置,可发呆,可固定,可持续。