📅  最后修改于: 2023-12-03 15:11:28.415000             🧑  作者: Mango
本文将会介绍在 Python 中使用 run_simple
启动 Flask 应用时的绑定(bind)过程。在第 1030 行的 s.bind(server_address)
,是在绑定服务器地址和端口,让服务器监听指定的地址和端口,从而开始接受客户端的请求。
def run_simple(hostname, port, application, use_reloader=False, use_debugger=False,
use_evalex=True, extra_files=None, reloader_interval=1, threaded=False,
processes=1, request_handler=None, static_files=None):
"""Start an application using a built-in server."""
if request_handler is None:
request_handler = WSGIRequestHandler
if ':' in hostname:
hostname = '[{}]'.format(hostname)
family = None
for res in socket.getaddrinfo(hostname, port, socket.AF_UNSPEC,
socket.SOCK_STREAM, socket.IPPROTO_TCP):
family, socktype, proto, _, _ = res
try:
s = socket.socket(family, socktype, proto)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
if hasattr(socket, 'SO_REUSEPORT'):
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
except socket.error as e:
s = None
continue
try:
s.bind((hostname, port))
break
except socket.error as e:
s.close()
s = None
continue
if s is None:
raise ConnectionError('Could not bind to %s:%s: %s' % (hostname, port, e))
server_address = (hostname, port)
try:
handler_class = request_handler
httpd = handler_class.get_server(application, server_address, log=app.logger, static_files=static_files)
except socket.error as e:
raise ConnectionError('Unable to start server: %s' % e)
display_hostname = hostname
if display_hostname.startswith('[') and display_hostname.endswith(']'):
display_hostname = display_hostname[1:-1]
protocol = 'https' if httpd.socket_context else 'http'
app.logger.info(' * Running on %s://%s:%d/ (Press CTRL+C to quit)', protocol, display_hostname, port)
if use_reloader:
# Remove pydevd_tracing.set_trace function from sys.settrace, which is considered as a side-effect
# by the reloader.
_cleanup()
if os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
# Disable reloader for subprocesses
use_reloader = False
else:
args = sys.argv[:]
if "--extra-files" in args:
index = args.index("--extra-files")
extra_files = args[index + 1]
use_reloader = True
if use_debugger:
trace = lambda *x: None # noqa: E731
else:
trace = _trace
#重要代码片段
reloader = Reloader(extra_files, reloader_interval, (use_debugger, use_evalex), not threaded, trace)
reloader.run_with_reloader(main_loop, extra_files, reloader_interval, [s], request_handler, fd=fd)
return
# Serve requests until process is killed
httpd.serve_forever()
首先,我们需要使用 socket
模块来创建 TCP 套接字,使用 socket.socket(family, socktype, proto)
来创建一个套接字,其中 family
是地址族(如 AF_INET
或 AF_INET6
),socktype
是套接字类型(如 SOCK_STREAM
或 SOCK_DGRAM
),proto
是协议类型(如 IPPROTO_TCP
或 IPPROTO_UDP
)。接着,设置 SO_REUSEADDR 和 SO_REUSEPORT 选项,以便服务器在关闭后可以立即重启。然后,使用 s.bind((hostname, port))
来将套接字绑定到服务器地址和端口。
需要注意的是,如果绑定失败,则会尝试使用其他地址和端口进行绑定,直到成功为止。如果最终无法成功绑定,则会抛出 ConnectionError
异常并提示相关信息。
最后,启动服务器,使其在指定的地址和端口上侦听来自客户端的请求,并提供相应的响应。