简评: 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 模块 https://docs.python.org/3/library/socket.html 提供了 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 调用和数据流的顺序:
TCP Socket Flow
左侧表示服务端, 右侧表示客户端.
从左上角的列开始, 注意服务器设置的 API 调用以设置「监听」socket:
- socket()
- bind()
- listen()
- accept()
listening socket 它监听来自客户端的连接, 当客户端连接时, 服务器调用 accept()来接受或完成连接.
客户端调用 connect()建立与服务器的连接并启动三次握手, 握手步骤很重要, 因为它确保连接的每一侧都可以在网络中访问, 换句话说, 客户端可以访问服务端, 反之亦然.
中间是往返部分, 使用 send()和 recv()在客户端和服务器之间交换数据.
在底部, 客户端和服务端关闭各自的 socket.
来源: http://www.jianshu.com/p/4b08accb04ab