Web服务器 = TCP服务器(七步走) + HTTP协议(请求、响应)
1.首先编写一个tcp服务端程序
import socket
# 创建socket实例
tcp_server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
tcp_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
tcp_server.bind('',8000)
tcp_server.listen(128)
#建立连接
while True:
conn,addr = tcp_server.accept()
server_data=conn.recv(1024).decode()
print(server_data)
response_data=''.encode()
conn.send(response_data)
conn.close()
tcp_server.close()
2.将response数据编写成http响应报文数据,此时我们只需要在建立连接处修改
首先我们先了解下http响应报文的格式
根据http响应报文的格式,我们写入响应行+响应头+空行+响应体
#建立连接
while True:
conn,addr = tcp_server.accept()
server_data=conn.recv(1024).decode()
print(server_data)
#相应行
response_line='HTTP/1.1 200 OK\r\n'
#响应头
response_header='Content-Type: text/html\r\n'
#相应体
response_body=('<html><head></head><body><div>你好</div></body>/html>')
response_data=(response_line+response_header+'\r\n').encode()+response_body
conn.send(response_data)
conn.close()
tcp_server.close()
此时你会发现web服务端依旧无法返回数据(是因为response_body是二进制内容)。所以我们应新建一个html文件,用with open来打开读取文件。
1.首先我们创建一个写有您好的html
2.通过with open导入
#建立连接
while True:
conn,addr = tcp_server.accept()
server_data=conn.recv(1024).decode()
print(server_data)
with open('index1.html','rb') as f:
file_data=f.read()
#相应行
response_line='HTTP/1.1 200 OK\r\n'
#响应头
response_header='Content-Type: text/html\r\n'
#相应体
response_data=file_data
response_data=(response_line+response_header+'\r\n').encode()+response_data
conn.send(response_data)
conn.close()
############################################################################################完整代码
import socket
# 创建socket实例
tcp_server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
tcp_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1)
tcp_server.bind(('',8000))
tcp_server.listen(128)
#建立连接
while True:
conn,addr = tcp_server.accept()
server_data=conn.recv(1024).decode()
print(server_data)
with open('index1.html','rb') as f:
file_data=f.read()
#相应行
response_line='HTTP/1.1 200 OK\r\n'
#响应头
response_header='Content-Type: text/html\r\n'
#相应体
response_data=file_data
response_data=(response_line+response_header+'\r\n').encode()+response_data
conn.send(response_data)
conn.close()
3.打开浏览器输入ip地址与服务器端口号我们就会得到一个写有您好的网页
这种格式目前不能返回指定页面的数据,无论你在导航栏输入什么都只会显示首页的数据。下面我们将学习如何返回指定页面的数据
首先我们先了解请求行的组成
由此我们可以看出在'/'后跟的是资源路径 并且在请求头里 请求方式 请求资源 协议版本之间是以 空格分割,此时我们可以使用字符串.split来返回'/'后的内容并且修改
import socket
# 创建socket实例
tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcp_server.bind(('', 9000))
tcp_server.listen(128)
# 建立连接
while True:
conn, addr = tcp_server.accept()
server_data = conn.recv(1024).decode()
print(server_data)
server_list=server_data.split(' ', maxsplit=2)
server_path=server_list[1]
print(server_path)
if server_path=='/':
server_path='/index2.html'
try:
with open('html'+server_path, 'rb') as f:
file_data = f.read()
# 相应行
response_line = 'HTTP/1.1 200 OK\r\n'
# 响应头
response_header = 'Content-Type: text/html\r\n'
# 相应体
response_data = file_data
response_data = (response_line + response_header + '\r\n').encode() + response_data
conn.send(response_data)
except Exception as e:
with open('html/index3.html', 'rb') as f:
file_data = f.read()
#响应行
response_line = 'HTTP/1.1 404 Not Found\r\n'
# 响应头
response_header = 'Content-Type: text/html\r\n'
# 相应体
response_data = file_data
response_data = (response_line + response_header + '\r\n').encode() + response_data
conn.send(response_data)
finally:
conn.close()