精通python——网络编程学习笔记

目录

1 网络编程介绍

1.1 客户端/服务器网络编程简述

1.2 通信端点

1.3 面向连接的套接字与无连接的套接字

2 模块介绍

2.1 Socket

2.2 SocketServer 模块

2.3 Twisted


1 网络编程介绍

1.1 客户端/服务器网络编程简述

服务器首先会创建一个通信端点,它能够使服务器监听请求;然后,监听服务器进入无限循环中,等待客户端的连接并响应它们的请求;最后,必须让潜在的客户知道存在这样的服务器来处理他们的需求。

客户端所需要做的只是创建它的单一通信端点,然后建立一个到服务器的连接。然后,客户端就可以发出请求,该请求包括任何必要的数据交换。一旦请求被服务器处理,且客户端收到结果或某种确认信息,此次通信就会被终止。

1.2 通信端点

套接字是计算机网络数据结构,也就是“通信端点”。

套接字最初是为同一主机上的应用程序所创建,使得主机上运行的一个程序(进程)与另一个运行的程序进行通信。这就是所谓的进程间通信(Inter Process Communication,IPC)。

有两种类型的套接字:基于文件的和面向网络的

  • 基于文件的:

UNIX 套接字家族AF_UNIX(又名 AF_LOCAL),代表地址家族(address family):UNIX,其缩写 AF;其他比较旧的系统可能会将地址家族表示成域(domain)或协议家族(protocol family),并使用其缩写 PF。

  • 面向网络的:

家族名字 AF_INET,或者地址家族:因特网。另一个地址家族 AF_INET6 用于第 6 版因特网协议(IPv6)寻址。

套接字地址:主机-端口对,一个网络地址由主机名和端口号对组成。

1.3 面向连接的套接字与无连接的套接字

面向连接的套接字
不管你采用的是哪种地址家族,都有两种不同风格的套接字连接。第一种是面向连接的,这意味着在进行通信之前必须先建立一个连接。

面向连接的通信提供序列化的、可靠的和不重复的数据交付,而没有记录边界。这基本上意味着每条消息可以拆分成多个片段,并且每一条消息片段都确保能够到达目的地,然后将它们按顺序组合在一起,最后将完整消息传递给正在等待的应用程序。

实现这种连接类型的主要协议是传输控制协议TCP,必须使用 SOCK_STREAM 作为套接字类型。

无连接的套接字
与虚拟电路形成鲜明对比的是数据报类型的套接字,它是一种无连接的套接字。这意味着,在通信开始之前并不需要建立连接。

在数据传输过程中并无法保证它的顺序性、可靠性或重复性。然而,数据报确实保存了记录边界,这就意味着消息是以整体发送的,而并非首先分成多个片段。

实现这种连接类型的主要协议是用户数据报协议UDP,必须使用 SOCK_DGRAM 作为套接字类型。

2 模块介绍

Python 提供了两个级别访问的网络服务模块:

    低级别的网络服务模块 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的全部方法。

    高级别的网络服务模块 SocketServer, 它提供了服务器中心类,可以简化网络服务器的开发。

当然还有Twisted,Twisted 是一个完整的事件驱动的网络框架,利用它既能使用也能开发完整的异步网络应
用程序和协议。

2.1 Socket

创建套接字,必须使用 socket.socket()函数:socket(socket_family, socket_type, protocol=0),返回一个套接字对象。

socket_family 是 AF_UNIX 或 AF_INET(如前所述),socket_type 是 SOCK_STREAM或 SOCK_DGRAM(也如前所述)。protocol 通常省略,默认为 0。

套接字对象(内置)方法:

创建 TCP 服务器:

ss = socket() #  创建服务器套接字
ss.bind() #  套接字与地址绑定
ss.listen() #  监听连接
inf_loop: #  服务器无限循环
    cs = ss.accept() #  接受客户端连接
    comm_loop: #  通信循环
        cs.recv()/cs.send() #  对话(接收 / 发送)
    cs.close() #  关闭客户端套接字
ss.close() #  关闭服务器套接字 # (可选)

所有套接字都是通过使用 socket.socket()函数来创建的。因为服务器需要占用一个端口并等待客户端的请求,所以它们必须绑定到一个本地地址。

调用 accept()函数之后,就开启了一个简单的(单线程)服务器,它会等待客户端的连接默认情况下,accept()是阻塞的,这意味着执行将被暂停,直到一个连接到达。

一旦服务器接受了一个连接,就会返回(利用 accept())一个独立的客户端套接字,用来与即将到来的消息进行交换。使用新的客户端套接字类似于将客户的电话切换给客服代表。当一个客户电话最后接进来时,主要的总机接线员会接到这个电话,并使用另一条线路将这个电话转接给合适的人来处理客户的需求。这将能够空出主线(原始服务器套接字),以便接线员可以继续等待新的电话(客户请求),而此时客户及其连接的客服代表能够进行他们自己的谈话。

一旦创建了临时套接字,通信就可以开始,通过使用这个新的套接字,客户端与服务器就可以开始参与发送和接收的对话中,直到连接终止。当一方关闭连接或者向对方发送一个空字符串时,通常就会关闭连接。

示例:

 第 6~13 行
HOST 变量是空白的,这是对 bind()方法的标识,表示它可以使用任何可用的地址。对于该应用程序,将缓冲区大小设置为 1KB。listen()方法的参数是在连接被转接或拒绝之前,传入连接请求的最大数。

在第 11 行,分配了 TCP 服务器套接字(tcpSerSock),紧随其后的是将套接字绑定到服务器地址以及开启 TCP 监听器的调用。

第 15~28 行

如果消息是空白的,这意味着客户端已经退出,所以此时我们将跳出对话循环,关闭当前客户端连接,然后等待另一个客户端连接。如果确实得到了客户端发送的消息,就将其格式化并返回相同的数据,但是会在这些数据中加上当前时间戳的前缀。最后一行永远不会执行,它只是用来提醒读者,如果写了一个处理程序来考虑一个更加优雅的退出方式。

创建 TCP 客户端:

cs = socket() #  创建客户端套接字
cs.connect() #  尝试连接服务器
comm_loop: #  通信循环
    cs.send()/cs.recv() #  对话(发送 / 接收)
cs.close() #  关闭客户端套接字

一旦客户端拥有了一个套接字,它就可以利用套接字的 connect()方法直接创建一个到服务器的连接。当连接建立之后,它就可以参与到与服务器的一个对话中。最后,一旦客户端完成了它的事务,它就可以关闭套接字,终止此次连接。

示例:

 创建 UDP 服务器:

ss = socket() #  创建服务器套接字
ss.bind() #  绑定服务器套接字
inf_loop: #  服务器无限循环
    cs = ss.recvfrom()/ss.sendto()  #  关闭(接收 / 发送)
ss.close()  #  关闭服务器套接字

创建 UDP 客户端:

cs = socket() #  创建客户端套接字
comm_loop: #  通信循环
    cs.sendto()/cs.recvfrom()  #  对话(发送 / 接收)
cs.close() #  关闭客户端套接字

socket 模块属性
除了现在熟悉的 socket.socket()函数之外,socket 模块还提供了更多用于网络应用开发的属性。

2.2 SocketServer 模块

SocketServer 是标准库中的一个高级模块,它的目标是简化很多样板代码,它们是创建网络客户端和服务器所必需的代码。

SocketServer 模块类:

创建 SocketServer TCP 服务器:

第 11~15 行
这里进行了大量的工作。我们得到了请求处理程序 MyRequestHandler,作为 SocketServer中 StreamRequestHandler 的一个子类,并重写了它的 handle()方法,该方法在基类 Request 中默认情况下没有任何行为。

当接收到一个来自客户端的消息时,它就会调用 handle()方法。而 StreamRequestHandler类将输入和输出套接字看作类似文件的对象,因此我们将使用 readline()来获取客户端消息,并利用 write()将字符串发送回客户端。因此,在客户端和服务器代码中,需要额外的回车和换行符。

创建 SocketServer TCP 客户端:

第 10~21 行
SocketServer 请求处理程序的默认行为是接受连接、获取请求,然后关闭连接。由于这个原因,我们不能在应用程序整个执行过程中都保持连接,因此每次向服务器发送消息时,都需要创建一个新的套接字。

2.3 Twisted

它提供了大量的支持来建立完整的系统,包括网络协议、线程、安全性和身份验证、聊天/ IM、DBM 及 RDBMS 数据库集成、Web/因特网、电子邮件、命令行参数、GUI 集成工具包等。

创建 Twisted Reactor TCP 服务器:

 第 8~14 行
我们获得protocol类并为时间戳服务器调用TSServProtocol。然后重写了 connectionMade()和 dataReceived()方法,当一个客户端连接到服务器时就会执行 connectionMade()方法,而当服务器接收到客户端通过网络发送的一些数据时就会调用dataReceived()方法。reactor 会作为该方法的一个参数在数据中传输,这样就能在无须自己提取它的情况下访问它。

第 16~20 行
在服务器代码的最后部分中,创建了一个协议工厂。它之所以被称为工厂,是因为每次得到一个接入连接时,都能“制造”协议的一个实例。然后在 reactor 中安装一个 TCP 监听器,以此检查服务请求。当它接收到一个请求时,就会创建一个 TSServProtocol 实例来处理那个客户端的事务。

创建 Twisted Reactor TCP 客户端:

第 8~22 行
类似于服务器,我们通过重写 connectionMade()和 dataReceived()方法来扩展 Protocol,并且这两者都会以与服务器相同的原因来执行。另外,还添加了自己的方法 sendData(),当需要发送数据时就会调用它。

参考:《python核心编程》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值