Sockets 和 socket API被用于在网络上发送消息。它们提供了进程间通信(IPC)的一种形式。而网络既可以是连接到计算机的本地网络,也可以是计算机被连接到外部的真实网络(比如Internet网)
本文用三种不同的迭代版本 实现socket服务端和客户端:
读完本文,你将了解如何使用Python socket module 中重要的函数和方法来实现client-server应用程序。同时向你展示了在endpoints端点
之间如何使用自定义的类来发送消息和数据,你可以在endpoints端点
之上构建并使用你的应用程序。
本文中的例子使用了Python3.6(source code on GitHub)。
网络和socket是个庞大的主题。当然,有很多关于它们的文章。如果你刚接触socket和网络,你会对其中大量的知识点和术语感到不知所措,这很正常。
不过,不要灰心。我已经为你写了这篇文章。就像我们学习Python一样,我们可以每次学一点知识。你可以收藏本文,当你知识储备足够时,再回过头来学习本文的下一章节。 好了,让我们开始吧。
Sockets有着悠久的历史。Sockets的使用最早出现在1971年的ARPNET中,之后在1983年发布的BSD 操作系统中成为了一个API,此时被称为Berkeley sockets。
当Internet随着万维网World Wide Web在1990年代的突然成功,网络编程也开始了腾飞。Web服务器和浏览器不是唯一的利用新建Internet网络和sockets的应用程序。Client-server 应用程序以不同的类型和规模被广泛的使用。
今天,虽然socket API使用的协议 随着时间已经演变和进化,我们也看到了一些新的socket API,但是底层的API仍旧没有变化。
最常用的socket应用程序是client-server应用程序,也就是一端作为server 并等待client的连接。也就是我们在本文要讲的 应用程序类型。更具体地,我们将了解 Internet sockets的socket API,有时会被称作BSD sockets或者Berkeley sockets。当然也会涉及到Unix domain sockets,Unix domain sockets只能用来在同一台主机上进行进程间的通信。
Python’s socket module提供了使用Berkeley sockets API的接口。在本文中,我们将使用和讨论该module。
该module中主要的socket API函数有:
socket()
bind()
listen()
accept()
connect()
connect_ex()
send()
recv()
close()
Python提供了方便并且前后一致的API,这些API直接映射到 系统调用,这些系统调用采用c实现。我们将在下一节 了解这些API是如何结合起来使用的。
As part of its standard library, Python also has classes that make using these low-level socket functions easier. Although it’s not covered in this tutorial, see the socketserver module, a framework for network servers. There are also many modules available that implement higher-level Internet protocols like HTTP and SMTP. For an overview, see Internet Protocols and Support.
作为标准库的一部分,Python也定义了一些类,来方便我们使用这些底层的socket function。虽然,本文不涉及这部分内容,但是可以查看 socketserver module文档,为network server实现的框架。Python中也有许多module实现了上层的Internet protocols,比如HTTP,SMTP。想对这些modules作个了解的话,可以查看Internet Protocols and Support文档。很快你就很看到,我们将使用socket.socket()
创建一个socket object,并使用socket.SOCK_STREAM
指定socket type。当你这样做的时候,默认使用的协议是 Transmission Control Protocol (TCP)。
为什么你应该使用TCP?The Transmission Control Protocol (TCP):
作为对比,使用socket.SOCK_DGRAM
创建的User Datagram Protocol (UDP) socket 是不可靠的,接受者读取的数据顺序 可能 和发送者写数据的顺序 不一致。
为什么TCP很重要呢?网络是一个尽最大努力进行传输的系统。网络并不能保证:1)你的数据会到达目的地 2)你将会接收到传送给你的数据
网络设备(比如,路由器,交换机)的可利用带宽是有限的,并且有着固有的系统限制(就行我们的clients和servers一样,有着CPUs,内存,总线,packet buffers等)。不使用TCP的话,你就不得不担心丢包packet loss,数据包到达顺序紊乱,还有在你通过网络进行通信时总是会发生的一些事情。
在下表中,TCP的socket API的调用顺序 和 数据的流动:
sockets-tcp-flow.jpg
左侧一栏代表server,右侧代表client。
从左侧一栏的上面开始,注意server调用API calls来设置一个监听socket:
socket()
bind()
listen()
accept()
一个listenning socket所做的事情,就像它的名字那样。它监听 来自client的连接。当client尝试连接时,server 调用accept()
来建立连接。
client 调用connect()
来建立 一个到server的连接,并 初始化 三次握手。握手的步骤是很重要的,因为握手确保了 连接的两端 在网络中 是可以访问到的,换句话说:client 可以访问到server,server也可以访问到client。有可能出现的情况是,只有一个主机(client or server)可以访问到另一端。
在上图的中间是 往返的部分,数据在client和server之间进行交换,使用send()
和recv()
这两个函数。
At the bottom, the client and server close() their respective sockets.
在上图的底部,client和serverclose()
它们各自的sockets
原文太长了,下回再译。 to be continued...
本文翻译自https://realpython.com/python-sockets/,转载请注明出处。