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 pandas.pivot_table() 函数
发布时间:2024/04/24 浏览次数:82 分类:Python
-
Python Pandas pivot_table()函数通过对数据进行汇总,避免了数据的重复。
在 Python 中将 Pandas 系列的日期时间转换为字符串
发布时间:2024/04/24 浏览次数:894 分类:Python
-
了解如何在 Python 中将 Pandas 系列日期时间转换为字符串
在 Python Pandas 中使用 str.split 将字符串拆分为两个列表列
发布时间:2024/04/24 浏览次数:1124 分类:Python
-
本教程介绍如何使用 pandas str.split() 函数将字符串拆分为两个列表列。
在 Pandas 中将 Timedelta 转换为 Int
发布时间:2024/04/23 浏览次数:231 分类:Python
-
可以使用 Pandas 中的 dt 属性将 timedelta 转换为整数。
Python 中的 Pandas 插入方法
发布时间:2024/04/23 浏览次数:112 分类:Python
-
本教程介绍了如何在 Pandas DataFrame 中使用 insert 方法在 DataFrame 中插入一列。
使用 Python 将 Pandas DataFrame 保存为 HTML
发布时间:2024/04/21 浏览次数:106 分类:Python
-
本教程演示如何将 Pandas DataFrame 转换为 Python 中的 HTML 表格。
如何将 Python 字典转换为 Pandas DataFrame
发布时间:2024/04/20 浏览次数:73 分类:Python
-
本教程演示如何将 python 字典转换为 Pandas DataFrame,例如使用 Pandas DataFrame 构造函数或 from_dict 方法。
如何在 Pandas 中将 DataFrame 列转换为日期时间
发布时间:2024/04/20 浏览次数:101 分类:Python
-
本文介绍如何将 Pandas DataFrame 列转换为 Python 日期时间。