傍晚时分,坐在屋檐下,看着天空慢慢变黑,我的心孤独而凄凉,我觉得我的生活被剥夺了。当时我是个年轻人,但我害怕这样生活和衰老。当时我是个年轻人,但我害怕这样生活和衰老。在我看来,这比死亡更可怕。--------王小波
在Python构建静态Web只需要服务器 python3 -m http.server 端口号( 不指定默认为8000的端口号。 这个命令可以完成。我以前见过一些安装包每次都放在服务器上。FTP麻烦,用http模块的方。
python在网络上包装一些内置模块,可以使用非常简单的代码实现端到端通信,如HTTP、RPC服务等。
在编写RPC和REST服务前,先复习一下常见的基础Socket一些端到端通信协议的模块。不管是RPC还是REST底层通信协议需要支持。
对于TCP和UPD协议,在常见的网络通信中,浏览器、电子邮件和其他一般应用程序通过数据收发TCP协议的,DNS当收发较短的控制数据时,通常会使用UDP。
创建TCP服务通过服务器实现服务器 TCP 协议和客户端通信。
创建一个 TCP 使用服务器的一个简单方法是socketserver库。让我们一起复习以下简单的内容TCP服务器
from socketserver import BaseRequestHandler, TCPServerclass EchoHandler(BaseRequestHandler): def handle(self): print('Got connection from', self.client_address) while True: #接收客户端发送的数据, 接收数据的最大字节是8192 msg = self.request.recv(8192) # 接收到的数据正在发送回来 if not msg: break self.request.send(msg)if __name__ == '__main__': # 20000端口,默认IP为本地IP,监听到消息交EchoHandler处理器 serv = TCPServer(('', 20000), EchoHandler) serv.serve_forever()
代码简单,指定IP暴露相应的端口,这里通过serv.serve_forever()确保连接始终存在。 Got connection from ('127.0.0.1', 1675)
建立服务端后,查看客户端
AF_INET:表示ipv4SOCK_STREAM: tcp传输协议>>> from socket import socket, AF_INET, SOCK_STREAM>>> s = socket(AF_INET, SOCK_STREAM)>>> s.connect(('localhost', 20000))>>> s.send(b'Hello')5>>> s.recv(8192)b'Hello'>>>
socketserver 这种服务器在默认情况下是单线程的,一次只能为客户端连接服务。若要通过多线程处理多个客户端,可初始化一个ForkingTCPServer 或者是ThreadingTCPServer对象。
from socketserver import ThreadingTCPServerif __name__ == '__main__': serv = ThreadingTCPServer(('', 20000), EchoHandler) serv.serve_forever()
使用 fork 或者线程服务器的一个潜在问题是,它们将为每个客户端连接创建一个新的过程或线程。由于客户端连接数量没有限制,恶意黑客可以同时发送大量连接,使服务器崩溃。由于客户端连接数量没有限制,恶意黑客可以同时发送大量连接,使服务器崩溃。
可以创建预分配大小的预分配 工作线程池或进程池首先创建普通的非线程服务器,然后在线程池中使用serve forever()启动它们的方法。
if __name__ == '__main__': from threading import Thread NWORKERS = 16 serv = TCPServer(('', 20000), EchoHandler) for n in range(NWORKERS): t = Thread(target=serv.serve_forever) t.daemon = True t.start() serv.serve_forever()
一般来讲,一个TCPServer实例化时,会绑定和激活相应的socket,如果 bind_and_activate 如果是真的,结构方法会自动调用server_bind() 和 server_activate()方法。其它参数传递给基类 BaseServer,有时我想通过设置一些选项来调整底部socket,可设置参数bind_and_activate=False。
if __name__ == '__main__': serv = TCPServer(('', 20000), EchoHandler, bind_and_activate=False) # Set up various socket options serv.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) # Bind and activate serv.server_bind() serv.server_activate() serv.serve_forever()
socket.SO_REUSEADDR允许服务器重新绑定以前使用过的端口号。它可以直接放置在类变量中,因为它必须经常使用 TCPServer上面设置
当然,你也可以直接使用原生工具而不使用工具。Socket的编写TCP服务端
from socket import socket, AF_INET, SOCK_STREAMdef echo_handler(address, client_sock): print('Got connection from{}'.format(address)) while True: msg = client_sock.recv(8192) if not msg: break client_sock.sendall(msg) client_sock.close()def echo_server(address, backlog=5): sock = socket(AF_INET, SOCK_STREAM) sock.bind(address) sock.listen(backlog) while True: client_sock, client_addr = sock.accept() echo_handler(client_addr, client_sock)if __name__ == '__main__': echo_server(('', 20000))
了解了TCP来看看服务通信。UDP的
创建UDP服务实现一个基础 UDP 协议服务器与客户端通信。
跟 TCP 一样,UDP 也可以使用服务器socketserver库容易创建。例如,以下是一个简单的时间服务器:
from socketserver import BaseRequestHandler, UDPServerimport timeclass TimeHandler(BaseRequestHandler): def handle(self): print('Got connection from', self.client_address) # Get message and client socket request 属性包括数据报和底层 socket 对象的元组 msg, sock = self.request resp = time.ctime() sock.sendto(resp.encode('ascii'), self.client_address)if __name__ == '__main__': serv = UDPServer(('', 20000), TimeHandler) serv.serve_forever()
测试一下
>>> from socket import socket, AF_INET, SOCK_DGRAM>>> s = socket(AF_INET, SOCK_DGRAM)>>> s.sendto(b'', ('localhost', 20000))0>>> s.recvfrom(8192)(b'Tue May 3 11:48:53 2022', ('127.0.0.1', 20000))>>>
对于UPD协议应使用数据报告的传输 socket 的sendto() 和 recvfrom() 方法,因为是面向无连接,没有连接步骤,但发生时要跟随接受方
在了解了基本的通信协议后,回到今天要谈的事情ERST接口。REST接口是基于HTTP协议的,而HTTP是直接依赖TCP协议栈负责约束表示层层
创造一个简单的REST接口使用使用 REST 接口通过网络远程控制或访问应用程序,但不想安装完整的应用程序 web 框架。
可以构建一个 REST 最简单的方法是创建一个基于风格的界面 WSGI 标准(W eb
电脑知识