单进程单线程最基础的socket web服务实现原理
#coding : uft-8
import socket
# ------------------------------------到这里做了一个响应头 + 响应体body-----------------------------------
EOL1 = b'\n\n' #转换为字节
EOL2 = b'\n\r\n'
body = '''Hello, world! <h1> from the5fire </h1>'''
response_params = [ #响应,一个字符串列表
'HTTP/1.0 200 OK', #状态200
'Date: sun, 27 may 2018 01:01:01 GMT', #日期
'Content-Type: text/html; charset=utf-8', #响应类型text utf-8文本
'Content-Length: {}\r\n'.format(len(body.encode())), #响应长度 .encode()以字节编码 len()长度 .format格式化len到的数字为字符串并传入{}
body,
]
response = '\r\n'.join(response_params) #以\r\n为连接将response_params列表元素转换为一个有格式的整体字符串
# -------------------------------------------------------接收请求,发送响应-----------------------------------
def handle_connection(conn,addr):
request = b""
while EOL1 not in request and EOL2 not in request:
request += conn.recv(1024)
conn.send(response.encode()) #把响应格式化之后发送给客户端
print(request) #b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8000\r\nConnection: keep-alive\r\nsec-ch-ua: " Not A;Brand";v="99", "Chromium";v="100", "Microsoft Edge";v="100"\r\nsec-ch-ua-mobile: ?0\r\nsec-ch-ua-platform: "Windows"\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 Edg/100.0.1185.50\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\nSec-Fetch-Site: none\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-User: ?1\r\nSec-Fetch-Dest: document\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6\r\nCookie: csrftoken=UNm1axaivMGs7ikC8YtX4SDOugU7lEyzFzpbecAUUCr3AyWRWqptEsPaIORFOvDm; sessionid=a20zdu52yvrhlezhelijneb2dus84llo\r\n\r\n'
print(response.encode())#b'HTTP/1.0 200 OK\r\nDate: sun, 27 may 2018 01:01:01 GMT\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: 38\r\n\r\nHello, world! <h1> from the5fire </h1>'
conn.close() #关闭连接
# -----------------------------------设置服务器ip端口,监听连接,转发请求去handle_connection------------------------
def main():
serversocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #创建socket连接 AF_INET=IPv4 SOCK_STREAM=TCP传输协议
serversocket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #设置端口复用,快速重启
serversocket.bind(('127.0.0.1',8000)) #设置访问IP和端口
serversocket.listen(5) #设置最大连接排队量
print('http://127.0.0.1:8000')
try:
while True:
conn, address = serversocket.accept() #(<socket.socket fd=120, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8000), raddr=('127.0.0.1', 55134)>, ('127.0.0.1', 55134))
handle_connection(conn,address)
finally: #无论try是否抛出异常,一定执行
serversocket.close() #关闭连接
if __name__ == '__main__':
main()
WSGI :Web Server负责监听某端口上的请求,传送给Web Application
WSGI:Web Application处理后设置状态和hander,返回body
WSGI :Web Server拿到返回数据后进行封装,返回给客户端完整的HTTP Response