[danger] 編寫client
1.拆分一個(gè)做協(xié)議判斷的方法socket_by_protocol
2.一個(gè)循環(huán)獲得服務(wù)器返回所有信息的方法response_by_socket
3.一個(gè)解析 header body 請(qǐng)求狀態(tài)碼的方法药有,巧妙利用元組可以被多個(gè)元素接受
4.在整體的大方法中魁袜,我們也可以用列表存儲(chǔ)代替if判斷
import socket,ssl
def socket_by_protocol(protocol):
"""
判斷使用http 還是https 協(xié)議
"""
if protocol == "http":
s = socket.socket()
else:
s = ssl.wrap_socket(socket.socket())
return s
def response_by_socket(s):
"""
參數(shù)是一個(gè) socket 實(shí)例
返回這個(gè) socket 讀取的所有數(shù)據(jù)
"""
response = b''
buffer_size = 1024
while True:
r = s.recv(buffer_size)
if len(r) == 0:
break
response += r
return response
def parsed_response(r):
"""
把 response 解析出 狀態(tài)碼 headers body 返回
狀態(tài)碼是 int
headers 是 dict
body 是 str
"""
header, body = r.split('\r\n\r\n', 1)
h = header.split('\r\n')
status_code = h[0].split()[1]
status_code = int(status_code)
headers = {}
for line in h[1:]:
k, v = line.split(': ')
headers[k] = v
return status_code, headers, body
def get(url):
protocol, host, port, path = parsed_url(url)
s = socket_by_protocol(protocol)
s.connect((host, port))
# 不用持續(xù)連接Connection: close
request = 'GET {} HTTP/1.1\r\nHost: {}\r\nConnection: close\r\n\r\n'.format(path, host)
s.send(request.encode("utf-8"))
response = response_by_socket(s)
r = response.decode("utf-8")
parsed_response(r)
status_code, headers, body = parsed_response(r)
if status_code in [301, 302]:
url = headers['Location']
return get(url)
return status_code, headers, body