执行mian ()函数
def main 函数():
创建套接字
重启占用的端口
绑定端口号
设置监听
循环 :
等待客户端的连接
创建进程
运行进程
关闭客户端连接
关闭套接字
def 进程函数(): ------为客户端返回数据------
接收客户端发送来的内容 (即http 请求 ) recv .decode ('utf-8')
编码后的内容直接用 正则 取出网页名 search("/\s*" , 或者 match( r"[ ^/] +(/[ ^ ] *)" ,
判断客户端请求的 文件 是否存在
存在则 打印 正则取出网页 .group()
判断设置默认网页
try:
拼接路径,在当前的 目录中寻找对应的文件读取
except:
如果没找到拼接错误的信息
响应行 =
响应头 =
响应体 = "错误...."
else:
没有错误则返回对应的文件
响应行 =
响应头 =
响应体 =
返回给客户端
import socket,re,os
a = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
b =a.bind(("",8989))
a.listen(128)
while True:
aa ,bb =a.accept()
jieshou = aa.recv(1024)
# print("接收:",jieshou)
bianma = jieshou.decode("utf-8")
# print("编码:",bianma)
zhengze =re.search("/\S*",bianma)
if zhengze:
jieguo = zhengze.group()
print("jieguo.............",jieguo)
if jieguo == "/":
jieguo = "/index.html"
if os.path.exists("static"+jieguo):
with open("static" + jieguo, "rb") as file:
# 读取文件中的全部数据
file_data = file.read()
# 响应行
response_line = "HTTP/1.1 200 OK\r\n"
# 响应头
response_header = "Server: PWS/1.1\r\nother:ok\r\nContent-Type: text/html;charset=utf-8\r\n"
# 响应体
response_body = file_data
# 组装http响应报文数据
response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
# 发送http 响应报文数据给客户端
aa.send(response_data)
# 关闭套接字
else:
with open("static"+"/"+"cuowu.html" ,"rb" )as cuowuxx_html:
cuwu_neirong = cuowuxx_html.read()
aaaa= cuwu_neirong.decode("utf-8")
# 响应行
response_line = "HTTP/1.1 404 Not Found\r\n"
# 响应头, 提示: 响应头信息程序员也可以根据自己的需要自定义一个响应头信息
# Content-Type: text/html;charset=utf-8: 服务器告诉浏览器数据的类型及编码格式
response_header = "Server: PWS/1.1\r\nother:ok\r\nContent-Type: text/html;charset=utf-8\r\n"
# 响应体
response_body = aaaa
# 组装http响应报文数据
response_data = (response_line + response_header + "\r\n" + response_body).encode("utf-8")
# 发送http 响应报文数据给客户端
aa.send(response_data)
aa.close()
代码实现:
import socket
import re
import multiprocessing
def service_client(new_socket):
"""为客户端返回数据"""
# 1. 接收浏览器发送过来的请求 ,即http请求相关信息
# GET / HTTP/1.1
# .....
request = new_socket.recv(1024).decode("utf-8")
#将请求头信息进行按行分解存到列表中
request_lines = request.splitlines()
# GET /index.html HTTP/1.1
file_name = ""
#正则: [^/]+ 不以/开头的至少一个字符 匹配到/之前
# (/[^ ]*) 以分组来匹配第一个字符是/,然后不以空格开始的0到多个字符,也就是空格之前
# 最后通过匹配可以拿到 请求的路径名 比如:index.html
ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
#如果匹配结果 不为none,说明请求地址正确
if ret:
#利用分组得到请求地址的文件名,正则的分组从索引1开始
file_name = ret.group(1)
print('FileName: ' + file_name)
#如果请求地址为 / 将文件名设置为index.html,也就是默认访问首页
if file_name == "/":
file_name = "/index.html"
# 2. 返回http格式的数据,给浏览器
try:
#拼接路径,在当前的html目录下找访问的路径对应的文件进行读取
f = open("./html" + file_name, "rb")
except:
#如果没找到,拼接响应信息并返回信息
response = "HTTP/1.1 404 NOT FOUND\r\n"
response += "\r\n"
response += "------file not found-----"
new_socket.send(response.encode("utf-8"))
else:
#如果找到对应文件就读取并返回内容
html_content = f.read()
f.close()
# 2.1 准备发送给浏览器的数据---header
response = "HTTP/1.1 200 OK\r\n"
response += "\r\n"
#如果想在响应体中直接发送文件内的信息,那么在上面读取文件时就不能用rb模式,只能使用r模式,所以下面将响应头和响应体分开发送
#response += html_content
# 2.2 准备发送给浏览器的数据
# 将response header发送给浏览器
new_socket.send(response.encode("utf-8"))
# 将response body发送给浏览器
new_socket.send(html_content)
# 关闭套接
new_socket.close()
def main():
"""用来完成整体的控制"""
# 1. 创建套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#用来重新启用占用的端口
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 2. 绑定IP和端口号
tcp_server_socket.bind(("", 7890))
# 3. 设置套接字监听连接数(最大连接数)
tcp_server_socket.listen(128)
while True:
# 4. 等待新客户端的链接
new_socket, client_addr = tcp_server_socket.accept()
# 5. 为连接上来的客户端去创建一个新的进程去运行
p = multiprocessing.Process(target=service_client, args=(new_socket,))
p.start()
#因为新进程在创建过程中会完全复制父进程的运行环境,所以父线程中关闭的只是自己环境中的套接字对象
#而新进程中因为被复制的环境中是独立存在的,所以不会受到影响
new_socket.close()
# 关闭监听套接字
tcp_server_socket.close()
if __name__ == "__main__":
main()