1 创建返回固定数据的web服务器:通过 localhost:8000/index.html 进行访问
import socket if __name__ == '__main__': # socket.AF_INET :IPv4 地址 socket.SOCK_STREAM:TCP链接 tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 设置端口号复用 程序退出 端口号释放 tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True) # 绑定端口号 tcp_server_socket.bind(('',8000)) # 设置监听 tcp_server_socket.listen(128) # 循环等待接收客户端的链接 while True: # 等待客户端的链接请求 new_socket,ip_prot = tcp_server_socket.accept() # 代码执行到此 说明链接成功 # 接受客户端的请求消息 recv_data = new_socket.recv(4096) print(recv_data) # 打开文件读取文件中的数据 with open("index.html","r",encoding='utf-8') as file: # 读取文件 file_data = file.read() # 设置响应行 response_line = "HTTP/1.1 200 Ok\r\n" # 设置响应头 response_Header = "Server:PWS/1.0\r\n" # 设置响应体 response_body = file_data # 拼接 响应体 response = response_line + response_Header + "\r\n" + response_body # 设置二级制数据 response_data = response.encode('utf-8') # 给服务端响应数据 new_socket.send(response_data) # 断开链接 new_socket.close()
2 根据不同的请求 返回不同的数据
import socket if __name__ == '__main__': # socket.AF_INET :IPv4 地址 socket.SOCK_STREAM:TCP链接 tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 设置端口号复用 程序退出 端口号释放 tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True) # 绑定端口号 tcp_server_socket.bind(('',8000)) # 设置监听 tcp_server_socket.listen(128) # 循环等待接收客户端的链接 while True: # 此刻代表链接成功 new_socket, ip_prot = tcp_server_socket.accept() # 接收客户端发送的消息 接收过来的是二进制消息 需要进行解码 recv_data = new_socket.recv(4096) # 对二进制消息进行解码 接收的是客户端 请求报文的消息 recv_content = recv_data.decode('utf-8') print(recv_content) # 对请求报文的消息 进行截取 获取URL地址栏的信息 request_list = recv_content.split(' ',maxsplit=2) # 根据空格截取 只截取最前面的两个 request_path = request_list[1] # /index.html # 读取文件 rb 模式兼容图片等 with open('./'+request_path,'rb',) as file: file_data = file.read() # 设置响应行 response_line = 'HTTP/1.1 200 OK\r\n' # 设置响应头 response_header = "Server:PWS/1.0\r\n" # 响应体 response_body = file_data # 进行拼接 转化为二进制 response = (response_line + response_header + "\r\n").encode('utf-8') + response_body # 给客户端响应消息 new_socket.send(response) # 关闭链接 new_socket.close()
3 处理发生错误的情况,比如访问的页面不存在返回404页面,比如 访问 / 返回index.html页面。
import socket def main(): # socket.AF_INET :IPv4 地址 socket.SOCK_STREAM:TCP链接 tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 设置端口号复用 程序退出 端口号释放 tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) # 绑定端口号 tcp_server_socket.bind(('', 8000)) # 设置监听 tcp_server_socket.listen(128) # 循环等待接收客户端的链接 while True: # 此刻代表链接成功 new_socket, ip_prot = tcp_server_socket.accept() # 接收客户端发送的消息 接收过来的是二进制消息 需要进行解码 recv_data = new_socket.recv(4096) # 判断接收的消息是否为空 如果是空的话就关闭链接 if len(recv_data) == 0: new_socket.close() return # 对二进制消息进行解码 接收的是客户端 请求报文的消息 recv_content = recv_data.decode('utf-8') print(recv_content) # 对请求报文的消息 进行截取 获取URL地址栏的信息 request_list = recv_content.split(' ', maxsplit=2) # 根据空格截取 只截取最前面的两个 request_path = request_list[1] # /index.html # 判断请求是否是跟目录 如果是返回index.html if request_path == "/": request_path = '/index.html' # 判断读取的文件是否存在 如果不存在返回 404 页面 try: # 读取文件 rb 模式兼容图片等 with open('./' + request_path, 'rb', ) as file: file_data = file.read() except Exception as e: with open("error.html",'rb') as file: file_data = file.read() # 设置响应行 response_line = 'HTTP/1.1 200 OK\r\n' # 设置响应头 response_header = "Server:PWS/1.0\r\n" # 响应体 response_body = file_data # 进行拼接 转化为二进制 response = (response_line + response_header + "\r\n").encode('utf-8') + response_body # 给客户端响应消息 new_socket.send(response) else: # 设置响应行 response_line = 'HTTP/1.1 200 OK\r\n' # 设置响应头 response_header = "Server:PWS/1.0\r\n" # 响应体 response_body = file_data # 进行拼接 转化为二进制 response = (response_line + response_header + "\r\n").encode('utf-8') + response_body # 给客户端响应消息 new_socket.send(response) finally: # 关闭链接 new_socket.close() if __name__ == '__main__': main()
4 创建多线程web服务器
import socket import threading def handle_client_request(new_socket): recv_data = new_socket.recv(4096) if len(recv_data) == 0: new_socket.close() return # 对二进制消息进行解码 接收的是客户端 请求报文的消息 recv_content = recv_data.decode('utf-8') print(recv_content) # 对请求报文的消息 进行截取 获取URL地址栏的信息 request_list = recv_content.split(' ', maxsplit=2) # 根据空格截取 只截取最前面的两个 request_path = request_list[1] # /index.html # 判断请求是否是跟目录 如果是返回index.html if request_path == "/": request_path = '/index.html' # 判断读取的文件是否存在 如果不存在返回 404 页面 try: # 读取文件 rb 模式兼容图片等 with open('./' + request_path, 'rb', ) as file: file_data = file.read() except Exception as e: with open("error.html", 'rb') as file: file_data = file.read() # 设置响应行 response_line = 'HTTP/1.1 200 OK\r\n' # 设置响应头 response_header = "Server:PWS/1.0\r\n" # 响应体 response_body = file_data # 进行拼接 转化为二进制 response = (response_line + response_header + "\r\n").encode('utf-8') + response_body # 给客户端响应消息 new_socket.send(response) else: # 设置响应行 response_line = 'HTTP/1.1 200 OK\r\n' # 设置响应头 response_header = "Server:PWS/1.0\r\n" # 响应体 response_body = file_data # 进行拼接 转化为二进制 response = (response_line + response_header + "\r\n").encode('utf-8') + response_body # 给客户端响应消息 new_socket.send(response) finally: # 关闭链接 new_socket.close() def main(): # socket.AF_INET :IPv4 地址 socket.SOCK_STREAM:TCP链接 tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 设置端口号复用 当服务端断开 端口号 可以使用 tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) # 绑定端口号 tcp_server_socket.bind(('',8000)) # 设置监听 tcp_server_socket.listen(128) # 建立链接 while True: new_socket, ip_prot = tcp_server_socket.accept() # 创建多线程 sub_thread = threading.Thread(target=handle_client_request,args=(new_socket,)) # 设置成为守护主线 sub_thread.setDaemon(True) # 启动子线程 sub_thread.start() if __name__ == '__main__': main()
5 使用类创建web服务器,创建一个处理数据的函数, 创建一个类(初始化websock,启动websocket)
import socket import threading def handle_client_request(new_socket): recv_data = new_socket.recv(4096) if len(recv_data) == 0: new_socket.close() return # 对二进制消息进行解码 接收的是客户端 请求报文的消息 recv_content = recv_data.decode('utf-8') print(recv_content) # 对请求报文的消息 进行截取 获取URL地址栏的信息 request_list = recv_content.split(' ', maxsplit=2) # 根据空格截取 只截取最前面的两个 request_path = request_list[1] # /index.html # 判断请求是否是跟目录 如果是返回index.html if request_path == "/": request_path = '/index.html' # 判断读取的文件是否存在 如果不存在返回 404 页面 try: # 读取文件 rb 模式兼容图片等 with open('./' + request_path, 'rb', ) as file: file_data = file.read() except Exception as e: with open("error.html", 'rb') as file: file_data = file.read() # 设置响应行 response_line = 'HTTP/1.1 200 OK\r\n' # 设置响应头 response_header = "Server:PWS/1.0\r\n" # 响应体 response_body = file_data # 进行拼接 转化为二进制 response = (response_line + response_header + "\r\n").encode('utf-8') + response_body # 给客户端响应消息 new_socket.send(response) else: # 设置响应行 response_line = 'HTTP/1.1 200 OK\r\n' # 设置响应头 response_header = "Server:PWS/1.0\r\n" # 响应体 response_body = file_data # 进行拼接 转化为二进制 response = (response_line + response_header + "\r\n").encode('utf-8') + response_body # 给客户端响应消息 new_socket.send(response) finally: # 关闭链接 new_socket.close() class HttpWebServer(): def __init__(self): # ipv4 地址 tcp链接 tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 端口号复用 tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True) # 设置端口号 tcp_server_socket.bind(('',8000)) # 设置监听 tcp_server_socket.listen(128) # 把tcp服务器作为web服务器使用 self.tcp_server_socket = tcp_server_socket # 启动服务器的方法 def start(self): while True: new_socket,ip_port = self.tcp_server_socket.accept() sub_thread = threading.Thread(target=handle_client_request,args=(new_socket,)) sub_thread.setDaemon(True) sub_thread.start() def main(): web_server = HttpWebServer() web_server.start() if __name__ == '__main__': main()