文章目录
. 题外话:私以为这本书挺好的,在讲一个大块的时候会先介绍相关的知识,然后再是在python中的应用,ps:我的python环境为3.6.2。
客户端/服务器架构
. 无论是软件还是硬件系统,相同的前提都是:服务器是一系列软件或硬件,为一个或多个客户端提供所需的“服务”,其存在的唯一目的就是等待客户端的请求,并响应它们,然后等待更多的需求。
从另一方面,客户端因特定的请求联系服务器,并发送必要的数据,然后等待服务器的回应,最后完成请求或给出故障的原因。客户端会对服务器进行一次性的请求,然后接受该服务,最后结束他们之间的事务,客户端每次发送的请求都被当做不同的事务。
硬件客户端/服务器架构
. 打印服务器是硬件服务器的一个例子。它们处理传入的打印作业并将其发送给系统中的打印设备。这样的计算机通常可以通过网络进行访问,并且客户端计算机向它发送打印请求。
另一个例子是文件服务器。这些通常是拥有庞大的存储容量的计算机,可悲客户端远程访问,支持文件服务器的一个最流行的网络操作系统是sun公司的网络文件系统(NFS)。它们的目的是让客户端访问网络磁盘和访问本地磁盘拥有相同的体验。
软件客户端/服务器架构
. 软件服务器也是运行在硬件之上,但是没有像硬件服务器那样的专用外围设备。软件服务器所提供的主要服务包括程序执行、数据传输检索、聚合、更新或其他类型的编程或数据操作。
一个常见的软件服务器是Web服务器。其一般拥有一台或多台计算机,在上面安装希望提供给用户的web页面和web应用程序,然后启动web服务器,接受来自客户端的请求,并向客户端回送web页面,然后等待下一个客户端的请求。这些服务器开启后会尽可能的保持长时间运行,除非受到一些外力驱使(如硬件故障)才会停止。
数据库服务器是另一种类型的软件服务器。其接受客户的存储或是检索请求,相应请求,然后的等待其它事务。
抽象理解
. 想像客户端/服务器架构如何工作的一个办法就是在脑海中构建一个画面。一个自动取款机(ATM),它服务每一个排队的客户,似乎永远也不会结束,这个队列可能很长,也可能空无一人,但在任何给定的某个时刻,都可能会出现一个客户。它就像一个无限循环的服务器,而每一个客户就是一个客户端,每个客户端都有一个需要解决的需求,当ATM处理完一个事务,客户就会离开,而ATM要么为下个客户服务,要么等待下一个客户的到来。
客户端/服务器网络编程
. 在服务器响应客户端请求之前,需要进行一些初步的设置流程来为之后的工作做准备:**首先会创建一个通信端点,**它能够使服务器监听请求,一旦一个通信端点已经建立,监听服务器就可以进入无限循环中,等待客户端的连接并响应它们的请求。
客户端比服务器端更简单,客户端需要做的只是创建它的单一通信端点,然后建立一个到服务器的连接。然后客户端就可以发出请求,该请求包括任何必要的数据交换。一旦请求被服务器处理,且客户端收到结果或收到某种确认信息,此次通信就会被终止。
套接字:通信端点
套接字
. 套接字是计算机网络数据结构,其体现了以上所说的“通信端点”的概念。在任何类型的通信开始之前,网络应用程序必须创建套接字。
套接字最初是为同一主机上的应用程序所创建,使得主机上运行的一个程序和另一个运行的程序进行通信(进程间通信)。有两种类型的套接字:基于文件的和面向网络的。
所讲套接字的第一个家族是Unix套接字,其拥有一个“家族名字”AF_UNIX(又名AF_LOCAL),它代表地址家族:Unix。包括Python之内的大多数受欢迎的平台都使用术语地址家族及其缩写AF。
因为两个进程运行在同一台计算机上,所以这些套接字都是基于文件的,这意味着文件系统支持它们的底层基础结构,因为文件系统是一个运行在同一个计算机上的多个进程之间的共享常量。
第二种类型的套接字是面向网络的,它也有自己的家族名字:AF_INET,或者地址家族:因特网。另一个地址家族AF_INET6用于第6版因特网协议(IPv6)寻址。其他还有别的地址家族,但是AF_INET是使用的最广泛的。
套接字地址:主机-端口号
. 一个网络地址由主机名和端口号组成,这是网络通信所需要的,此外并未事先说明有人在另一端进行接听,因为可能浏览一个网页出现“无法连接服务器”等情况。
有效的端口号范围是0~65535(尽管小于1024的)。如果正在使用POSIX兼容系统(如Linux、Mac OS X等),那么可以在/etc/services文件中找到预留端口号的列表(以及服务器/协议和套接字类型)。
面向连接的套接字与无连接的套接字
. 不论采用哪种地址家族,都有两种不同风格的套接字连接。
面向连接的套接字
. 这种套接字意味着在进行通信之前需要建立一个连接,这种类型的连接又称为虚拟电路或流套接字。
面向连接的通信提供序列化的、可靠的和不重复的数据交付,而没有记录边界。这基本上意味着每条消息可以拆分为多个片段,且每条消息片段都能确保到达目的地,然后将它们按照顺序组合到一起,最后将完整的消息传递给正在等待的应用程序。
实现这种连接类型的主要协议是传输控制协议(TCP)。为了创建TCP套接字,必须使用SOCK_STREAM作为套接字类型。因为这些套接字的网络版本使用因特网协议(IP)来搜寻网络中的主机,所以整个系统通常结合这两种协议来运行。
无连接的套接字
. 与虚拟电路形成鲜明对比的是数据报类型的套接字,它是一种无连接的套接字。这意味着在通信开始之前并不需要建立连接。此时,在数据传输的过程中并无法保证它的顺序性、可靠性或重复性。然而,数据报确实保存了记录边界,这就意味着消息是以整体发送的,而并非首先分为多个片段。
这种方式就像是邮政服务,信件和包裹或许并不能以发送顺序到达,事实上可能都不会到达。为了将其添加到并发通信中,在网络中甚至有可能存在重复的消息。
既然有这么多副作用,那为什么还要使用数据报呢?这是因为面向连接的套接字所提供的保证导致它们的设置以及对虚拟电路连接的维护需要大量的开销,而数据报不需要这些开销。因此它们通常能提供更好的性能,并可能适合一些类型的应用程序。
实现这种连接类型的主要协议是用户数据包协议(UDP),为创建UDP套接字,必须使用SOCK_DGRAM作为套接字类型(其名字来源于单词“datagram”——数据报)。因为这些套接字也使用因特网协议来寻找网络中的主机,所以这个系统也有一个两种协议的组合名字UDP/IP。