简评:socket 和 socket API 用于通过网络发送消息,它们提供了一种进程间通信(IPC)方式。网络可以是计算机的逻辑本地网络,也可以是物理连接到外部网络的网络,显而易见的例子是因特网(即 Internet, 可以通过 ISP 连接)。
背景:
Socket 历史悠久,其使用开始于 1971 年的 ARPANET,后来成为 1983 年发布的 Berkeley Software Distribution(BSD)操作系统中的 API,称为 Berkeley Socket。
当互联网在 20 世纪 90 年代随万维网腾飞时,网络编程也是如此,Web服务器和浏览器并不是利用新连接的网络和使用 socket 的唯一应用程序,各种类型和规模的客户端 - 服务器应用程序也都得到了广泛的使用。
现在虽然 socket API 使用的底层协议已经发展多年,而且我们也已经看到了新协议,但是底层 API 仍然保持不变。最常见的 socket 应用类型是客户端 - 服务器应用程序,其中一方充当服务器并等待来自客户端的连接。
Socket API 概述
Python 的 socket 模块提供了 Berkeley socket API 的接口,这是我们后续使用和讨论的模块。
此模块中的主要 socket API 函数和方法有:
socket()
bind()
listen()
accept()
connect()
connect_ex()
send()
recv()
close()
Python 提供了一个方便且一致的 API,可以直接映射到这些系统调用。另外,作为标准库的一部分,Python 还提供了使这些底层 socket 函数更容易使用的类。虽然本文未涉及,但请参阅socketserver 模块(网络服务器的框架)。还有许多模块可用于实现 HTTP 和 SMTP 等更高级别的 Internet 协议。
TCP Sockets
很快将看到,我们使用 socket.socket()
创建一个socket 对象,并将 socket 类型指定为socket.SOCK_STREAM,执行此操作时,使用的默认协议是传输控制协议(即 TCP)。
为什么是 TCP?
- 可靠:发送方检测并重新发送网络中丢弃的数据包。
- 有序的数据传递:应用程序按发送方编写的顺序读取数据。
相反,使用 socket.SOCK_DGRAM 创建的用户数据报协议(即 UDP)socket 是不可靠的,接收方读取的数据的顺序可能与发送方的写入顺序不同。
其重要性在于网络是尽力而为的交付系统,我们无法保证数据能够到达目的地,或者收到已发送的数据。
网络设备(例如,路由器和交换机)具有可用的有限带宽以及它们自身固有的系统限制,就像我们的客户端和服务器一样它们有 CPU、内存、总线和接口数据包缓冲区,使用 TCP 则不必担心数据包丢失,数据无序到达以及在通过网络进行通信时会发生的许多其他问题。
在下图中,让我们看一下 TCP 的 socket API 调用和数据流的顺序:
左侧表示服务端,右侧表示客户端。
从左上角的列开始,注意服务器设置的 API 调用以设置「监听」socket:
socket()
bind()
listen()
accept()
listening socket 它监听来自客户端的连接,当客户端连接时,服务器调用accept()
来接受或完成连接。
客户端调用connect()
建立与服务器的连接并启动三次握手,握手步骤很重要,因为它确保连接的每一侧都可以在网络中访问,换句话说,客户端可以访问服务端,反之亦然。
中间是往返部分,使用send()
和recv()
在客户端和服务器之间交换数据。
在底部,客户端和服务端关闭各自的 socket。
原文链接:Socket Programming in Python (Guide) – Real Python
推荐阅读:这些是 Python 官方推荐的最好书籍