Python 网络编程简介
本教程将介绍 Python 中的套接字以及如何使用 socket 模块在 Python 中构建 HTTP 服务器和客户端。 它还将涵盖 Tornado,这是一个 Python 网络库,非常适合长轮询、WebSockets 和其他需要与每个用户建立长期连接的应用程序。
什么是套接字?
套接字是两个应用程序之间的链接,可以相互通信(在一台机器上本地或在不同位置的两台机器之间远程)。
基本上,套接字充当两个实体(即服务器和客户端)之间的通信链路。 服务器将给出客户端请求的信息。 例如,当我们访问此页面时,浏览器创建了一个套接字并连接到服务器。
socket 模块
为了创建套接字,我们可以使用 socket.socket()
函数,语法非常简单:
import socket
s= socket.socket (socket_family, socket_type, protocol=0)
以下是参数的描述:
- socket_family:表示地址(和协议)族。 它可以是 AF_UNIX 或 AF_INET。
- socket_type:表示套接字类型,可以是SOCK_STREAM或SOCK_DGRAM。
- protocol:这是一个可选参数,通常默认为 0。
获得套接字对象后,我们可以使用套接字模块中可用的方法根据需要创建服务器或客户端。
创建一个简单的客户端
在我们开始之前,让我们看看 Python 中可用的客户端套接字方法。
-
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-
s.connect():
启动 TCP 服务器连接
要创建一个新套接字,首先要导入套接字类的套接字方法。
import socket
接下来,我们将创建一个流 (TCP) 套接字,如下所示:
stream_socket = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
AF_INET
参数表示我们正在请求 Internet 协议 (IP) 套接字,特别是 IPv4。 第二个参数是 TCP 套接字的传输协议类型 SOCK_STREAM
。 此外,我们还可以通过指定套接字 AF_INET6
参数来创建 IPv6 套接字。
指定服务器。
server = "localhost"
指定我们要与之通信的端口。
port =80
将套接字连接到服务器正在侦听的端口。
server_address = ((host, port))
stream_socket.connect(server_address)
重要的是要注意主机和端口必须是一个元组。
向服务器发送数据请求:
message = 'message'
stream_socket.sendall(message)
从服务器获取响应:
data = sock.recv(10)
print(data)
要关闭连接的套接字,我们可以使用 close
方法:
stream_socket.close()
以下是客户端/服务器的完整代码。
import socket
# Create a TCP/IP socket
stream_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Define host
host = 'localhost'
# define the communication port
port = 8080
# Connect the socket to the port where the server is listening
server_address = ((host, port))
print("connecting")
stream_socket.connect(server_address)
# Send data
message = 'message'
stream_socket.sendall(message.encode())
# response
data = stream_socket.recv(10)
print(data)
print('socket closed')
构建一个简单的服务器
现在让我们来看看一个简单的 Python 服务器。 以下是 Python 中可用的套接字服务器方法。
-
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-
s.bind()
:将地址(主机名、端口号)绑定到套接字。 -
s.listen()
:设置并启动 TCP 侦听器。 -
s.accept()
:接受 TCP 客户端连接。
我们将按照以下步骤进行:
- 创建套接字。
- 将套接字绑定到端口。
- 开始接受套接字上的连接。
这是服务器程序。
import socket
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Define host
host = 'localhost'
# define the communication port
port = 8080
# Bind the socket to the port
sock.bind((host, port))
# Listen for incoming connections
sock.listen(1)
# Wait for a connection
print('waiting for a connection')
connection, client = sock.accept()
print(client, 'connected')
# Receive the data in small chunks and retransmit it
data = connection.recv(16)
print('received "%s"' % data)
if data:
connection.sendall(data)
else:
print('no data from', client)
# Close the connection
connection.close()
服务器现在已准备好接收传入连接。
现在在单独的终端窗口中运行客户端和服务器程序,这样它们就可以相互通信了。
服务端输出
$ python server.py
waiting for a connection
('127.0.0.1', 45504) connected
received "b'message'
客户端输出
$ python client.py
connecting
b'message'
socket closed
要查看当前正在使用哪些端口,可以使用 netstat -ntlp
命令,如下所示。
Tornado 框架
Tornado 框架是可用于 Python 网络编程的库之一。 在本节中,我们将讨论这个库并展示如何使用它来构建 WebSocket。
Tornado 是一个 Python 网络框架和异步网络库。 Tornado 使用非阻塞网络 I/O,因此能够扩展到数万个打开的连接。 这种特性使其成为长轮询、WebSockets 和其他需要与每个用户建立长期连接的应用程序的理想选择。
让我们创建一个简单的 Tornado WebSocket:
import tornado.ioloop
import tornado.web
class ApplicationHandler(tornado.web.RequestHandler):
def get(self):
self.message = message = """<html>
<head>
<title>Tornado Framework</title>
</head>
<body
<h2>Welcome to the Tornado framework</h2>
</body>
</html>"""
self.write(message)
if __name__ == "__main__":
application = tornado.web.Application([
(r"/", ApplicationHandler),
])
application.listen(5001)
tornado.ioloop.IOLoop.instance().start()
在上面的代码中:
-
我们定义类
ApplicationHandler
,它用作请求的处理程序并使用write()
方法返回响应。 - main 方法是程序的入口。
-
tornado.web.Application
为 Web 应用程序创建一个基础,并采用一组处理程序,即ApplicationHandler
。 - 该应用程序侦听端口 5000,客户端可以使用同一端口与该应用程序通信。
-
tornado.ioloop.IOLoop.instance().start()
为应用程序创建一个非阻塞线程。
如果我们运行该应用程序,我们将得到如下屏幕截图所示的结果。
Tornado 还集成了 asyncio 模块,允许您在同一个事件循环中使用这两个库。 Asyncio 是一个 Python 库,可让您使用 async/await 语法编写协程。
同步与异步编程
同步编程是按顺序完成任务的地方。 所有任务都遵循特定的顺序; 这意味着每个任务都在下一个任务开始之前从头到尾完成。
同步编程的一个缺点是,如果一个特定任务的执行时间相当长,则后续任务必须等待该任务完成; 这会造成延误。
然而,异步编程意味着任务可以同时发生,而无需等待其他作业完成执行。
异步通信主要用于聊天应用程序以及显示实时数据的应用程序。
异步编程可以节省从 API 获取数据的时间。 从 API 获取数据或发出 HTTP 请求可能需要比预期更长的时间; 您可以在 HTTP 调用上应用异步函数,而不是等待 http 请求完成。 异步调用释放程序以继续在其他区域执行。
异步编程的另一个优点是,如果我们发出多个请求,并且其中一个请求突然停止,这不会影响其他请求,因为程序可以转到下一个任务。
假设我们有一个应用程序多次请求外部 API 服务器。 使用同步编程,应用程序将不得不等到后续 API 完成 HTTP 请求并返回响应,从而使您的应用程序变慢。
例如,假设我们要请求一个外部 API,例如天气 API。 让我们使用 Tornado 执行同步和异步调用以获取天气信息。
# synchronous function
from tornado.httpclient import HTTPClient
key = 'my_secret_key'
def get_weather():
city = 'london'
url = 'https://api.weatherapi.com/v1/current.json?key='+key+'&q='+city+'&aqi=no'
print(url)
http_client = HTTPClient()
response = http_client.fetch(url)
return (response.body)
# Asynchronous function
from tornado.httpclient import AsyncHTTPClient
secret_key = 'my_secret_key'
async def get_weather():
city = 'london'
url = 'http://api.weatherapi.com/v1/current.json?key='+key+'&q='+city+'&aqi=no'
print(url)
http_client = AsyncHTTPClient()
response = await http_client.fetch(url)
return (response.body)
总结
到目前为止,大家一定已经掌握了 Python 套接字编程的基础知识以及如何构建简单的服务器和客户端。 随意构建自己的聊天客户端进行试验。 有关详细信息,请访问官方 Python 文档。
相关文章
Python 中的第一类函数
发布时间:2023/04/25 浏览次数:113 分类:Python
-
第一类函数是被语言视为对象或变量的函数。 我们可以将它们分配给变量或将它们作为对象传递给其他函数。Python 支持第一类函数的功能。
Python 函数参数类型
发布时间:2023/04/25 浏览次数:140 分类:Python
-
在这篇 Python 文章中,我们将学习 Python 中使用的函数参数类型。 我们还将学习如何编写不带参数的 Python 函数。
Python 生成器中的 send 函数
发布时间:2023/04/25 浏览次数:111 分类:Python
-
本教程将介绍如何在 Python 中使用生成器的 send() 函数。我们可以创建一个像迭代器一样运行的函数,并且可以通过 Python 生成器函数在 for 循环中使用。
Python Functools 偏函数
发布时间:2023/04/25 浏览次数:80 分类:Python
-
本文介绍了我们如何使用分部函数,该函数随 functools 库一起提供,并附有示例。 这显示了调用时如何传递属性和部分函数。
Python main() 函数中的参数
发布时间:2023/04/25 浏览次数:157 分类:Python
-
在本教程结束时,我们应该了解Python 中在 main() 中使用参数是否是一种好的做法。
Python 中的内置 identity 函数
发布时间:2023/04/25 浏览次数:88 分类:Python
-
identity 函数只是一个返回其参数的函数。 当我们定义一个恒等函数并赋值时,它会返回该值。在本教程结束时,我们将了解 Python 是否具有内置的 identity 函数。
在 Python 中拟合阶跃函数
发布时间:2023/04/25 浏览次数:177 分类:Python
-
阶跃函数是带有看起来像一系列步骤的图形的方法。 它们由一系列中间有间隔的水平线段组成,也可以称为阶梯函数。本文给出了阶跃函数的简单演示。
在 Python 中创建双向链表
发布时间:2023/04/25 浏览次数:54 分类:Python
-
双向链表是指由称为节点的顺序链接的记录集组成的链接数据结构。 每个节点包含一个前一个指针、一个下一个指针和一个数据字段。
将 Python 类对象序列化为 JSON
发布时间:2023/04/25 浏览次数:152 分类:Python
-
本教程介绍序列化过程。 它还说明了我们如何使用 toJSON() 方法使 JSON 类可序列化,并包装 JSON 以转储到其类中。