TutorialsPoint Python 网络编程教程

来源：https://www.yiibai.com/python_network_programming/

Python网络编程

原文：https://www.yiibai.com/python_network_programming

Python网络编程是关于使用python作为编程语言来处理计算机网络需求。 例如，如果创建和运行本地Web服务器，或者从带有模式的URL自动下载某些文件。

面向读者

本教程适用于愿意使用Python作为编程语言以简单易学的步骤学习网络编程的计算机科学专业的毕业生以及软件专业人士。

前提条件

在继续本教程之前，应该具有Python编程语言编写代码，使用任何python IDE以及执行Python程序的基本知识。 如果您是python的新手，请参考Python教程以更好地理解熟悉Python语言。

教程目录

编号 | 主题 | 描述
1 | Python网络编程简介 | python非常适合网络编程领域。随着云计算的增长，网络编程已成为一个更加热门的话题，而python扮演着重要的角色。
2 | Python网络编程开发环境 | Python 3适用于Windows，Mac OS和大多数Linux操作系统。，介绍如何在这些系统上安装Python3.
3 | Python Internet协议模块 | Internet协议旨在在世界各地所有与Internet连接的计算机上实现统一的地址系统，并使数据包能够从Internet的一端传输到另一端。
4 | Python IP地址 | python模块ipaddress广泛用于验证IP地址并将其分类为IPV4和IPV6类型。 它还可以用于比较IP地址值以及用于处理ip地址的IP地址算法。
5 | Python DNS查找 | 演示如何使用python模块dnspython管理域名到IP地址的转换，该模块还提供了查找CNAME和MX记录的方法。
6 | Python路由 | 路由有助于更好地管理网页的结构，并显着提高网站的性能，并且进一步的增强或修改将变得非常简单。
7 | Python HTTP请求 | 在Python中使用requests模块创建http请求，它是一个非常强大的模块，除了简单的请求和响应数据外，还可以处理http通信的许多方面。 它可以处理身份验证，压缩/解压缩，分块请求等。
8 | Python HTTP响应 | Web浏览器是客户端，托管网站的计算机是服务器。 在收到客户端的请求后，服务器会生成响应并将其以某种格式发送回客户端。
9 | Python HTTP标头 | 客户端和服务器之间的请求和响应涉及消息中的标头和正文。 标头包含特定于协议的信息，这些信息在通过TCP连接发送的原始消息的开头出现。
10 | Python自定义HTTP请求 | 超文本传输协议（HTTP）是用于启用客户端和服务器之间的通信的协议，它用作客户端和服务器之间的请求-响应协议。
11 | Python请求状态代码 | 响应消息具有状态码。 它是一个三位数的整数，状态码的第一位数定义了响应的类别，而后两位则没有任何分类作用。
12 | Python HTTP验证 | 认证是确定请求是否来自具有使用系统所需特权的有效用户的过程。
13 | Python HTTP数据下载 | 演示如何使用处理ftp或文件传输协议的python模块从serer下载数据。
14 | Python连接重用 | Python提供了urllib3模块，该模块具有一些方法来处理客户端和服务器之间的连接重用。
15 | Python网络接口 | 在一台机器上有多个接口时，需要跟踪它们的名称，状态等。Python可以列出接口及其状态。
16 | Python Socket程序 | Python提供对特定应用程序级网络协议（例如FTP，HTTP等）的更高级别访问的库。
17 | Python HTTP客户端 | 在http协议中来自客户端的请求到达服务器，假定它是有效请求并获取一些数据和元数据。
18 | Python HTTP服务器 | Python标准库带有内置的网络服务器，可以通过程序分配端口号，并通过该端口访问Web服务器。
19 | Python构建URL | Python requests模块可以帮助构建URLS并动态处理URL值。
20 | Python Web表单提交 | 与网页的交互需要一些数据通过html页面中的表单提交给服务器。requests模块使用带有所需参数的POST方法优雅地处理此问题。
21 | Python数据库和SQL | Python编程语言具有用于数据库编程的强大功能，Python还支持数据定义语言（DDL），数据操作语言（DML）和数据查询语句。
22 | Python Telnet | 在Python中，telnet由telnetlib模块实现，此模块具有Telnet类，该类具有建立Telnet连接所需的方法。
23 | Python电子邮件 | Python具有EmailMessage类，可用于构建电子邮件。 此类是自定义电子邮件消息不同部分（如TO和FROM标记，主题行以及电子邮件内容）所需的方法。
24 | Python SMTP | Python提供的smtplib模块中的SMTP对象具有一个称为sendmail的实例方法，该方法通常用于完成邮件的发送工作。
25 | Python POP3 | pop3协议是用于从电子邮件服务器下载邮件信息的电子邮件协议。
26 | Python IMAP | Python的客户端库imaplib用于通过imap协议访问电子邮件。
27 | Python SSH | SSH或安全套接字Shell，是一种网络协议，提供了一种访问远程计算机的安全方式。
28 | Python FTP | FTP或文件传输协议是一种众所周知的网络协议，用于在网络中的计算机之间传输文件。
29 | Python SFTP | FTP也称为SSH文件传输协议。它是一种网络协议，可通过任何可靠的数据流提供文件访问，文件传输和文件管理。
30 | Python Web服务器 | Python具有足够的通用性，可以创建许多类型的应用程序和驱动互联网或其他计算机网络的程序。
31 | Python上传数据 | 使用处理ftp或文件传输协议的python模块将数据上传到服务器。
32 | Python代理服务器 | 代理服务器用于通过另一台服务器浏览到某些网站，以便浏览保持匿名。
33 | Python列出目录 | Python可用于从目录获取内容列表。可以使用程序列出运行python的同一台计算机中目录的内容。
34 | Python远程过程调用 | 远程过程调用（RPC）系统使我们可以使用在本地库中调用函数时所使用的语法来调用远程服务器上可用的函数。

易百教程移动端：请扫描本页面底部(右侧)二维码并关注微信公众号，回复："教程" 选择相关教程阅读或直接访问：http://m.yiibai.com 。

Python网络编程简介

原文：https://www.yiibai.com/python_network_programming/python_network_programming_introduction.html

随着python多年来作为一种编程语言的多功能性的发展，python也非常适合网络编程领域。随着云计算的增长，网络编程已成为一个更加热门的话题，而python扮演着重要的角色。以下是python用作网络编程首选语言的几个重要原因。

1. 套接字编程

套接字是客户端和服务器之间进行通信的连接。例如，当打开浏览器时，会自动创建一个套接字来与服务器连接。Python有一个套接字模块，可用于实现各种套接字功能，例如绑定地址或启动侦听器端口。套接字编程是计算机网络的基础，而python可以很好地处理它。

2. 客户端编程

客户端是请求信息并等待响应的计算机。可以编写Python程序来验证许多客户端操作，例如解析URL，在提交请求时使用URL发送参数，如果无法成功访问一个URL则连接到备用URL等。这些程序在客户端程序中运行，并且即使不使用浏览器，也可以处理与服务器的所有通信需求。例如，您可以提供python程序的URL来下载文件，该URL将由程序本身完成，而无需浏览器程序的帮助。

3. 构建Web服务器

Python可以创建简单的Web服务器，使其足以使用python作为编程语言来运行网站。Python已经有一些内置的Web服务器，可以对其进行调整以实现所需的一些其他功能。

SimpleHTTPServer模块提供了开箱即用的Web服务器功能，您可以从本地python安装开始运行它。在python 3中，它的名称为http.serverCherryPy和Tornado是用python编写的Web服务器的示例，其运行效果与非python知名的Web服务器(如Apache或Ngnix)一样好。

1. 网页抓取

python出名的重要原因之一是它在抓取网络所用的语言中占主导地位。它的数据结构和网络访问能力使其非常适合访问网页并自动下载其数据。而且，如果目标网站有一些API连接可用，则python将通过其程序结构更轻松地对其进行处理。

1. Python Web框架

Web Frame通过提供预定义的结构和模块化，使应用程序开发变得轻松快捷。开发人员必须进行最少的编码才能利用这些现有库并进行一些自定义以实现目标。Django和Flask是两个著名的公司，尽管它们是开源的，但它们已经在商业上得到了广泛应用。

1. 获取地理位置

Python具有处理地理数据的库。如果知道纬度和经度，则可以找到公司地址的名称，反之亦然。当然，它需要其他地图提供商的数据(例如Google地图)的帮助。Python的联网功能可以扩展到不同的地理边界。

Python网络编程开发环境

原文：https://www.yiibai.com/python_network_programming/python_network_environment.html

Python 3适用于Windows，Mac OS和大多数Linux操作系统。尽管Python 2可用于许多其他操作系统，但Python 3尚未提供对Python 2的支持，所以这里不建议再使用。

1. 本地环境设置

打开一个终端窗口，然后键入python以检查是否已经安装Python，以及安装了Python的哪个版本。

2. 获取Python

Windows平台

此下载页面上提供了最新版本的Python 3(Python 3.5.1)的二进制文件。可以使用以下不同的安装软件包：

Windows x86-64 embeddable zip file

Windows x86-64 executable installer

Windows x86-64 web-based installer

Windows x86 embeddable zip file

Windows x86 executable installer

Windows x86 web-based installer

注：安装Python 3.5.1的最低操作系统要求是Windows 7 SP1。对于3.0至3.4.x版本，可以在Windows XP上安装。

Linux平台

不同版本的Linux使用不同的软件包管理器来安装新软件包。在Ubuntu Linux上，使用以下命令从终端安装Python 3。

$ sudo apt-get install python3-minimal

如要从源安装

从Python的下载URL下载Gzip压缩源tarball - https://www.python.org/ftp/python/3.5.1/Python-3.5.1.tgz

Extract the tarball
tar xvfz Python-3.5.1.tgz
Configure and Install:
cd Python-3.5.1
./configure --prefix = /opt/python3.5.1
make
sudo make install

苹果系统

从此URL下载Mac OS安装程序 - https://www.python.org/downloads/mac-osx/

Mac OS X 64位/32位安装程序 - python-3.5.1-macosx10.6.pkg
Mac OS X 32位i386/PPC安装程序 - python-3.5.1-macosx10.5.pkg

双击该程序包文件，然后按照向导说明进行安装。
最新的源代码，二进制文件，文档，新闻等可在Python的官方网站上找到，Python官方网站 - https://www.python.org/

可以从以下站点下载Python文档。文档有HTML，PDF和PostScript格式。Python文档网站 - www.python.org/doc/

3. 设置路径

程序和其他可执行文件可以在许多目录中。但是需要为操作系统提供了一个搜索路径，这个路径列出了它搜索可执行文件的目录。

重要特征是 -

路径存储在环境变量中，此变量是操作系统维护的命名字符串。变量包含命令外壳和其他程序可用的信息。

path变量在Unix中被命名为PATH，在Windows中被命名为Path(Unix区分大小写； Windows不区分大小写)。

在Mac OS中，安装程序将处理路径详细信息。要从任何特定目录调用Python解释器，必须将Python目录添加到路径中。

4. 在Unix / Linux上设置路径

要将Python目录添加到Unix中特定会话的路径 -

在csh shell中键入setenv PATH "$PATH:/usr/local/bin/python3"并按Enter。
在bash shell(Linux)中键入export PYTHONPATH=/usr/local/bin/python3.4并按Enter。
在sh或ksh shell中键入PATH="$PATH:/usr/local/bin/python3"并按Enter。

注意 - /usr/local/bin/python3是Python目录的路径。

5. 在Windows上设置路径

要将Python目录添加到Windows中特定会话的路径。在命令提示符下 - 键入%path%;C:\Python并按Enter。

注意 - C:\Python是Python目录的路径。

6. 运行Python

有三种启动Python的不同方式 -

交互式解释
可以从Unix，DOS或任何其他提供命令行解释器或Shell窗口的系统中启动Python。在命令行输入python。立即在交互式解释器中开始编码。

$python             # Unix/Linux

#或者

python%             # Unix/Linux

#或者

C:> python           # Windows/DOS

集成开发环境

如果您的系统上有支持Python的GUI应用程序，则也可以从图形用户界面(GUI)环境中运行Python。

Unix - IDLE是第一个用于Python的Unix IDE。

Windows - PythonWin是Python的第一个Windows界面，是带有GUI的IDE。

Macintosh - 可以从主网站上获得Macintosh版本的Python和IDLE IDE，可以将其下载为MacBinary或BinHex文件。

如果无法正确设置环境，则可以寻求系统管理员的帮助。确保正确设置了Python环境，并且工作正常。

注–后续章节中提供的所有示例均使用Windows 7和Ubuntu Linux上的Python 3.4.1版本执行。

经过上面步骤，我们已经建立了Python编程环境，以便在学习理论的同时可以执行所有的示例。也可以修改这些示例并执行。

Python Internet协议模块

原文：https://www.yiibai.com/python_network_programming/python_internet_protocol.html

Internet协议旨在在世界各地所有与Internet连接的计算机上实现统一的地址系统，并使数据包能够从Internet的一端传输到另一端。诸如Web浏览器之类的程序应该能够在任何位置连接到主机，而无需知道每个数据包在其运行过程中所经过的网络设备有多复杂。Internet协议有各种类别。创建这些协议是为了满足Internet中不同计算机之间不同类型的数据通信的需求。

Python有几个模块可以处理这些通信中的每一个场景。这些模块中的方法和功能可以完成仅验证URL的最简单工作，也可以完成处理Cookie和会话的复杂工作。在本章中，我们将介绍用于互联网协议的常见python模块。

协议 | Python模块 | 描述
HTTP | urllib.request | 打开HTTP URL
HTTP | urllib.response | 为网址请求创建响应对象
HTTP | urllib.parse | 要在诸如(寻址方案，网络位置，路径等)组件中分解统一资源定位符(URL)字符串。
HTTP | urllib.robotparser | 它确定特定的用户代理是否可以在发布了robots.txt文件的网站上获取URL。
FTP | ftplib | 实现FTP协议的客户端。可以使用它来编写执行各种自动FTP作业的Python程序，例如镜像其他FTP服务器。
POP | poplib | 此模块定义了POP3类，该类封装了与POP3服务器的连接以从电子邮件服务器读取消息。
IMAP | imaplib | 此模块定义了三个类，即IMAP4，IMAP4_SSL和IMAP4_stream，它们封装了与IMAP4服务器的连接以读取电子邮件。
SMTP | smtplib | smtplib模块定义了一个SMTP客户端会话对象，该对象可用于通过SMTP listner守护程序将邮件发送到任何Internet计算机。
Telnet | telnet | 此模块提供Telnet类，该类实现Telnet协议以访问远程服务器。

在后面的章节中将详细讨论它们。

Python IP地址

原文：https://www.yiibai.com/python_network_programming/python_ip_address.html

IP地址(Internet协议)是一种基本的网络概念，可在网络中提供地址分配功能。python模块ipaddress广泛用于验证IP地址并将其分类为IPV4和IPV6类型。它还可以用于比较IP地址值以及用于处理ip地址的IP地址算法。

1. 验证IPV4地址

ip_address函数验证IPV4地址。如果值的范围超出0到255，则将引发错误。

print (ipaddress.ip_address(u'192.168.0.255'))
print (ipaddress.ip_address(u'192.168.0.256'))

当运行上面的程序时，得到以下输出-

192.168.0.255
ValueError: u'192.168.0.256' does not appear to be an IPv4 or IPv6 address

2. 验证IPV6地址

ip_address函数验证IPV6地址。如果值的范围超出0到ffff，则将引发错误。

print (ipaddress.ip_address(u'FFFF:9999:2:FDE:257:0:2FAE:112D'))

#invalid IPV6 address
print (ipaddress.ip_address(u'FFFF:10000:2:FDE:257:0:2FAE:112D'))

当运行上面的程序时，得到以下输出-

ffff:9999:2:fde:257:0:2fae:112d
ValueError: u'FFFF:10000:2:FDE:257:0:2FAE:112D' does not appear to be an IPv4 or IPv6 address

3. 检查IP地址的类型

我们可以提供各种格式的IP地址，并且该模块将能够识别有效格式。它还将指示它是IP地址的类别。

print type(ipaddress.ip_address(u'192.168.0.255'))

print type(ipaddress.ip_address(u'2001:db8::'))

print ipaddress.ip_address(u'192.168.0.255').reverse_pointer

print ipaddress.ip_network(u'192.168.0.0/28')

当运行上面的程序时，得到以下输出-

255.0.168.192.in-addr.arpa
192.168.0.0/28

4. IP地址比较

可以对IP地址进行逻辑比较，以确定它们是否相等。还可以比较一个IP地址的值是否大于另一个IP地址的值。

print (ipaddress.IPv4Address(u'192.168.0.2') > ipaddress.IPv4Address(u'192.168.0.1'))
print (ipaddress.IPv4Address(u'192.168.0.2') == ipaddress.IPv4Address(u'192.168.0.1'))
print (ipaddress.IPv4Address(u'192.168.0.2') != ipaddress.IPv4Address(u'192.168.0.1'))

当运行上面的程序时，得到以下输出-

True
False
True

5. IP地址算术

还可以应用算术运算来操纵IP地址。可以在IP地址中添加或减去整数。如果相加后最后一个八位位组的值超过255，则前一个八位位组将递增以容纳该值。如果多余的值不能被任何先前的八位位组吸收，则将引发值错误。

print (ipaddress.IPv4Address(u'192.168.0.2')+1)

print (ipaddress.IPv4Address(u'192.168.0.253')-3)

# Increases the previous octet by value 1.
print (ipaddress.IPv4Address(u'192.168.10.253')+3)

# Throws Value error
print (ipaddress.IPv4Address(u'255.255.255.255')+1)

当运行上面的程序时，得到以下输出-

192.168.0.3
192.168.0.250
192.168.11.0
AddressValueError: 4294967296 (>= 2**32) is not permitted as an IPv4 address

Python DNS查找

原文：https://www.yiibai.com/python_network_programming/python_dns_look_up.html

将IP地址转换为可读格式或单词后，便称为域名。域名到IP地址的转换由python模块dnspython管理。该模块还提供了查找CNAME和MX记录的方法。

1. 查找“ A”记录

在下面的程序中，我们使用dns.resolver方法找到该域的IP地址。通常，IP地址和域名之间的这种映射也称为“A”记录。

import dnspython as dns
import dns.resolver

result = dns.resolver.query('yiibai.com', 'A')
for ipval in result:
    print('IP', ipval.to_text())

运行上面示例代码，得到以下结果：

('IP', u'112.124.103.85')

2. 查找CNAME值

CNAME记录也称为规范名称记录，是域名系统(DNS)中的一种记录类型，用于将域名映射为另一个域的别名。CNAME记录始终指向另一个域名，并不能直接为IP地址。在下面的查询方法中，我们指定CNAME参数以获取CNAME值。

import dnspython as dns
import dns.resolver
result = dns.resolver.query('mail.google.com', 'CNAME')
for cnameval in result:
    print ' cname target address:', cnameval.target

运行上面示例代码，得到以下结果：

cname target address: googlemail.l.google.com.

3. 查找MX记录

MX记录(也称为邮件交换器记录)是域名系统中的资源记录，它指定负责代表接收者域的电子邮件消息的邮件服务器。如果有多个邮件服务器可用，它还会设置优先级值，该优先级值用于优先安排邮件传递。与上述程序类似，可以在查询方法中使用“MX”参数找到MX记录的值。

result = dns.resolver.query('mail.google.com', 'MX')
for exdata in result:
    print ' MX Record:', exdata.exchange.text()

运行上面示例代码，得到以下结果：

MX Record:    ASPMX.L.GOOGLE.COM.
MX Record:    ALT1.ASPMX.L.GOOGLE.COM.
MX Record:    ALT2.ASPMX.L.GOOGLE.COM.

以上是示例输出，而不是确切的输出。

Python路由

原文：https://www.yiibai.com/python_network_programming/python_routing.html

路由是将URL直接映射到创建网页的代码的机制。它有助于更好地管理网页的结构，并显着提高网站的性能，并且进一步的增强或修改将变得非常简单。在python中，路由是在大多数网络框架中实现的。我们将在本章中看到flask Web框架中的示例。

Flask路由

Flask中的route()装饰器用于将URL绑定到函数。当在浏览器中访问对应URL时，将执行该函数以给出结果。此处，URL => /hello规则绑定到hello_world()函数。如果用户访问URL => http://localhost:5000/ ，则hello_world()函数的输出将在浏览器中显示。

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
   return 'Hello Yiibai'

if __name__ == '__main__':
   app.run()

当运行上面的程序时，得到以下输出-

* Serving Flask app "flask_route" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [06/Aug/2019 09:48:45] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [06/Aug/2019 09:48:46] "GET /favicon.ico HTTP/1.1" 404 -
127.0.0.1 - - [06/Aug/2019 09:48:46] "GET /favicon.ico HTTP/1.1" 404 -

打开浏览器并指向URL=> http://localhost：5000/以查看函数执行的结果。

2. 使用URL变量

我们可以使用路由传递URL变量以动态构建URL。使用url_for()函数，该函数将函数名称作为第一个参数，并将其余参数作为URL规则的可变部分。

在下面的示例中，我们将函数名称作为参数传递给url_for()函数，并在执行这些行时打印出结果。

from flask import Flask, url_for
app = Flask(__name__)

@app.route('/')
def index(): pass

@app.route('/login')
def login(): pass

@app.route('/user/')
def profile(username): pass

with app.test_request_context():
    print url_for('index')
    print url_for('index', _external=True)
    print url_for('login')
    print url_for('login', next='/')
    print url_for('profile', username='fit su')

当我们运行上面的程序时，得到以下输出-

/
http://localhost/
/login
/login?next=%2F
/user/fit%20su

3. 重定向

可以使用重定向功能通过路由将用户重定向到另一个URL。提到了新的URL作为函数的返回值，该函数应该重定向用户。当我们在修改网页的一些问题时，将用户暂时转移到其他页面时，这很有用。

from flask import Flask, abort, redirect, url_for
app = Flask(__name__)

@app.route('/')
def index():
    return redirect(url_for('login'))

@app.route('/login')
def login():
    abort(401)
#    this_is_never_executed()

执行以上代码后，基本URL会转到使用中止功能的登录页面，因此永远不会执行登录页面的代码。

Python HTTP请求

原文：https://www.yiibai.com/python_network_programming/python_http_requests.html

http或超文本传输协议适用于客户端服务器模型。通常，Web浏览器是客户端，托管网站的计算机是服务器。在python中，我们使用requests模块创建http请求。它是一个非常强大的模块，除了简单的请求和响应数据外，还可以处理http通信的许多方面。它可以处理身份验证，压缩/解压缩，分块请求等。

HTTP客户端以请求消息的形式向服务器发送HTTP请求，该消息包括以下格式：

请求行；

零个或多个标头(General | Request | Entity)字段，后跟CRLF；

空行(即在CRLF之前没有任何内容的行)指示标头字段的结尾；

消息正文(可选)；

以下各节说明了HTTP请求消息中使用的每个实体。

1. 请求行

请求行以方法令牌开头，然后是请求URI和协议版本，最后以CRLF结尾。元素由空格SP字符分隔。

Request-Line = Method SP Request-URI SP HTTP-Version CRLF

让我们讨论请求行中提到的每个部分。

请求方法
请求方法表示要对由给定Request-URI标识的资源执行的方法。该方法区分大小写，应始终以大写形式提及。下表列出了HTTP/1.1中所有受支持的方法。

让我们讨论请求行中提到的每个部分。

2. 请求方法

请求方法表示要对由给定Request-URI标识的资源执行的方法。该方法区分大小写，应始终以大写形式。下表列出了HTTP/1.1中所有受支持的方法。

编号 | 方法 | 描述
1 | GET | GET方法用于使用给定URI从给定服务器检索信息。使用GET的请求应仅检索数据，而对数据没有其他影响。
2 | HEAD | 与GET相同，但只传输状态行和标头部分。
3 | POST | POST请求用于使用HTML表单将数据发送到服务器，例如，客户信息，文件上传等。
4 | PUT | 使用上载的内容替换目标资源的所有当前表示形式。
5 | DELETE | 删除URI给定的目标资源的所有当前表示形式。
6 | CONNECT | 建立到由给定URI标识的服务器的隧道。
7 | OPTIONS | 描述目标资源的通信选项。
8 | TRACE | 与目标资源的路径一起执行消息回送测试。

3. Request-URI

Request-URI是统一资源标识符，用于标识在其上应用请求的资源。以下是指定URI的最常用形式：

Request-URI = "*" | absoluteURI | abs_path | authority

当HTTP请求不适用于特定资源而是服务器本身时，将使用星号*；仅当所使用的方法不一定适用于资源时，才使用星号*。例如：

OPTIONS * HTTP/1.1

向代理发出HTTP请求时，将使用absoluteURI。请求代理转发来自有效缓存的请求或服务，并返回响应。例如：

GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1

Request-URI的最常见形式是用于标识源服务器或网关上的资源的形式。例如，希望直接从原始服务器检索资源的客户端将创建到主机“ www.w3.org” 的端口80的TCP连接，并发送以下行：

GET /pub/WWW/TheProject.html HTTP/1.1

Host: www.w3.org

4. 使用Python请求

我们将使用requests模块来了解http请求。安装：

pip install requests

在下面的示例中，我们看到一个简单的GET请求的情况，并打印出响应的结果。选择打印前300个字符。

# How to make http request
import requests as req
r = req.get('http://www.yiibai.com/python/')
print(r.text)[0:300]

Python HTTP响应

原文：https://www.yiibai.com/python_network_programming/python_http_response.html

http或超文本传输协议适用于客户端服务器模型。通常，Web浏览器是客户端，托管网站的计算机是服务器。在收到客户端的请求后，服务器会生成响应并将其以某种格式发送回客户端。

在接收并解释了请求消息后，服务器将以HTTP响应消息进行响应：

状态行

零个或多个标头(General | Response | Entity)字段，后跟CRLF

空行(即CRLF之前没有任何内容的行)指示标题字段的末尾

可选的消息正文

以下各节说明了HTTP响应消息中使用的每个实体。

1. 消息状态行

状态行由协议版本，后面的数字状态代码及其关联的文本短语组成。元素由空格SP字符分隔。

Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF

2. HTTP版本

支持HTTP版本1.1的服务器将返回以下版本信息：

HTTP-Version = HTTP/1.1

3. 状态码

Status-Code元素是一个三位数的整数，其中Status-Code的第一位定义响应的类别，最后两位不具有任何分类作用。第一位数字有5个值：

编号 | 状态码 | 描述
1 | 1xx | 信息性：表示已收到请求，并且该过程正在继续。
2 | 2xx | 成功：表示已成功接收，理解并接受了该动作。
3 | 3xx | 重定向：表示必须采取进一步的措施才能完成请求。
4 | 4xx | 客户端错误：请求包含不正确的语法或无法实现。
5 | 5xx | 服务器端错误：服务器无法满足有效的请求。

HTTP状态代码是可扩展的，不需要HTTP应用程序来了解所有已注册状态代码的含义。

4. 使用Python请求

在下面的python程序中，使用urllib3模块发出http GET请求并接收包含数据的响应。它还提供了响应代码，该响应代码也由模块中的功能管理。PoolManager对象处理连接池的所有详细信息，还处理线程安全性。

import urllib3
http = urllib3.PoolManager()

resp = http.request('GET', 'http://yiibai.com/robots.txt')
print resp.data

# get the status of the response
print resp.status

当我们运行上面的程序时，得到类似以下输出 -

User-agent: *
Disallow: /tmp
Disallow: /logs
Disallow: /rate/*
Disallow: /cgi-bin/*
Disallow: /video/video_course_view.php?*
Disallow: /video/course_view.php?*
Disallow: /videos/*
Disallow: /*/*_question_bank/*
Disallow: //*/*/*/*/src/*

200

Python HTTP标头

原文：https://www.yiibai.com/python_network_programming/python_http_headers.html

客户端和服务器之间的请求和响应涉及消息中的标头和正文。标头包含特定于协议的信息，这些信息出现在通过TCP连接发送的原始消息的开头。消息的正文与标头使用空白行分隔。

标头字段

http响应中的标头可以分为以下类型。以下是标头的说明和示例。

Cache-Control
Cache-Control general-header字段用于指定所有缓存系统必须遵守的指令。语法如下：

Cache-Control : cache-request-directive|cache-response-directive

HTTP客户端或服务器可以使用“Cache-Control”常规标头来指定缓存参数或从缓存中请求某些类型的文档。缓存指令在逗号分隔的列表中指定。例如：

Cache-control: no-cache

Connection
连接通用标头字段允许发送者指定该特定连接所需的选项，并且代理不能通过其他连接传达这些选项。以下是使用连接头的简单语法：

Connection : "Connection"

HTTP/1.1为发送方定义了“off”连接选项，以指示响应完成后将关闭连接。例如：

Connection: close

默认情况下，HTTP 1.1使用持久连接，该连接在事务处理后不会自动关闭。另一方面，HTTP 1.0默认情况下不具有持久连接。如果1.0客户端希望使用持久连接，则它使用keep-alive参数，如下所示：

Connection: keep-alive

Date
所有HTTP日期/时间戳都以格林威治标准时间(GMT)表示。允许HTTP应用程序使用日期/时间戳的以下三种表示形式中的任何一种：

Sun, 06 Nov 1994 08:49:37 GMT  ; RFC 822, updated by RFC 1123
Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
Sun Nov  6 08:49:37 1994       ; ANSI C's asctime() format

Transfer-Encoding

Transfer-Encoding字段指示已将哪种类型的转换应用于消息正文，以便在发送者和接收者之间安全地进行转换。这与内容编码不同，因为传输编码是消息的属性，而不是实体主体的属性。Transfer-Encoding标头字段的语法如下：

Transfer-Encoding: chunked

所有传输编码值都不区分大小写。

Upgrade
Upgrade通用标头允许客户端指定其支持的其他通信协议，并在服务器认为适合切换协议时使用。例如：

Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11

Upgrade标头字段旨在提供一种从HTTP/1.1过渡到其他不兼容协议的简单机制。

Via

网关和代理必须使用Via通用标题来指示中间协议和接收者。例如，可以将请求消息从HTTP/1.0用户代理发送到名为“fred”的内部代理，该代理使用HTTP/1.1将请求转发到位于nowhere.com的公共代理，代理通过以下方式完成请求：将其转发到位于 www.ics.uci.edu 的原始服务器。www.ics.uci.edu 接收到的请求将具有以下Via标头字段：

Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)

Warning

Warning通用标头用于携带有关消息状态或转换的其他信息，这些信息可能未反映在消息中。一个响应可能包含多个警告标头。

Warning : warn-code SP warn-agent SP warn-text SP warn-date

标头示例

在下面的示例中，使用urllib2模块使用urlopen获得响应。接下来应用info()方法来获取该响应的标头信息。

import urllib2
response = urllib2.urlopen('http://www.yiibai.com/python')
html = response.info()
print html

当我们运行上面的程序时，得到以下输出-

Access-Control-Allow-Headers: X-Requested-With
Access-Control-Allow-Origin: *
Cache-Control: max-age=2592000
Content-Type: text/html; charset=UTF-8
Date: Mon, 02 Jul 2019 20:15:07 GMT
Expires: Wed, 01 Aug 2019 20:15:07 GMT
Last-Modified: Sun, 01 Jul 2019 20:15:38 GMT
Server: ECS (tir/CDD1)
Vary: Accept-Encoding
X-Cache: HIT
Content-Length: 22063
Connection: close

Python自定义HTTP请求

原文：https://www.yiibai.com/python_network_programming/python_custom_http_requests.html

超文本传输协议(HTTP)是用于启用客户端和服务器之间的通信的协议。它用作客户端和服务器之间的请求-响应协议。请求设备称为客户端，发送响应的设备称为服务器。

urllib是传统的python库，在python程序中用于处理http请求。但是现在有了urllib3，它的功能比urllib过去的要多。我们导入urllib3库，以查看python如何使用它来发出http请求并接收响应。可以通过选择请求方法来自定义请求的类型。

pip install urllib3

示例

在下面的示例中，我们使用PoolManager()对象来处理http请求的连接详细信息。接下来使用request()对象通过POST方法发出一个http请求。最后，还使用json库以json格式打印接收到的值。

import urllib3
import json

http = urllib3.PoolManager()
r = http.request(
    'POST',
    'http://httpbin.org/post',
    fields={'field': 'value'})
print json.loads(r.data.decode('utf-8'))['form']

执行上面示例代码，得到以下结果：

{field': value'}

使用查询的URL

还可以传递查询参数来构建自定义URL。在下面的示例中，request方法使用查询字符串中的值来完成URL，该URL可以被python程序中的另一个函数进一步使用。

import requests

query = {'q': 'river', 'order': 'popular', 'min_width': '800', 'min_height': '600'}
req = requests.get('https://pixabay.com/en/photos/', params=query)

print(req.url)

执行上面示例代码，得到以下结果：

https://pixabay.com/en/photos/?q=river&min_width=800&min_height=600&order=popular

Python请求状态代码

原文：https://www.yiibai.com/python_network_programming/python_request_status_codes.html

在接收并解释了请求消息后，服务器将以HTTP响应消息进行响应。响应消息具有状态码。它是一个三位数的整数，其中状态码的第一位数定义了响应的类别，而后两位则没有任何分类作用。第一位数字有5个值：

状态码

编号 | 状态码 | 描述
1 | 1xx: Informational | 表示已收到请求，并且该过程正在继续。
2 | 2xx: Success | 表示已成功接收，理解并接受了该动作。
3 | 3xx: Redirection | 表示采取进一步的措施才能完成请求。
4 | 4xx: Client Error | 表示请求包含不正确的语法或无法实现。
5 | 5xx: Server Error | 表示服务器无法满足看似有效的请求。

成功响应

在下面的示例中，我们从URL访问文件，并且响应成功。所以返回的状态码是200：

import urllib3
http = urllib3.PoolManager()

resp = http.request('GET', 'http://yiibai.com/robots.txt')
print resp.data

# get the status of the response
print resp.status

执行上面代码，得到以下结果：

User-agent: *
Disallow: /tmp
Disallow: /logs
Disallow: /rate/*
Disallow: /cgi-bin/*
Disallow: /vtutorials/video_course_view.php?*
Disallow: /vtutorials/course_view.php?*
Disallow: /videos/*
Disallow: /*/*_question_bank/*
Disallow: //*/*/*/*/src/*

200

不成功响应

在下面的示例中，我们从不存在的url访问文件。响应不成功。因此，返回的状态码是403。

import urllib3
http = urllib3.PoolManager()

resp = http.request('GET', 'http://yiibai.com/robot.txt')
print resp.data

# get the status of the response
print resp.status

执行上面代码，得到以下结果：

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /robot.txt
on this server.</p>
</body></html>

403

Python HTTP验证

原文：https://www.yiibai.com/python_network_programming/python_http_authentication.html

验证是确定请求是否来自具有使用系统所需特权的有效用户的过程。在计算机网络世界中，这是非常重要的要求，因为许多系统保持相互交互，并且需要适当的机制来确保这些程序之间仅发生有效的交互。

python模块名称requests具有内置功能，可以调用服务网络应用提供的各种API以及用户凭据。这些凭据必须嵌入在调用程序中。如果API成功验证，则发生有效登录。

安装请求

我们安装了所需的名为请求的python模块，用于运行身份验证程序。

pip install requests

向Github进行身份验证

在下面，我们看到一种仅包含用户名和密码的简单身份验证机制。成功的响应表明有效的登录。

import requests
r = requests.get('https://api.github.com/user', auth=('user', 'pass'))
print r

验证到Twitter

还可以运行一个程序来使用twitter的api，并通过使用以下代码来成功登录。使用请求模块中可用的OAuth1方法来处理Twitter API所需的参数。如我们所见，requests模块能够处理更复杂的身份验证机制，涉及密钥和令牌，而不仅仅是用户名和密码机制。

import requests
from requests_oauthlib import OAuth1

url = 'https://api.twitter.com/1.1/account/verify_credentials.json'
auth = OAuth1('YOUR_APP_KEY', 'YOUR_APP_SECRET',
              'USER_OAUTH_TOKEN', 'USER_OAUTH_TOKEN_SECRET')

requests.get(url, auth=auth)

执行上面示例代码，得到以下结果：

{
  "errors": [
    {
      "code": 215,
      "message": "Bad Authentication data."
    }
  ]
}

Python HTTP数据下载

原文：https://www.yiibai.com/python_network_programming/python_http_data_download.html

可以使用处理ftp或文件传输协议的python模块从serer下载数据。还可以读取数据，然后将其保存到本地系统。
需要安装模块ftplib来实现此目的。

pip install ftplib

提取文件

可以使用getfile方法获取特定文件。此方法将文件的副本从远程系统移动到启动ftp连接的本地系统。

import ftplib
import sys

def getFile(ftp, filename):
    try:
        ftp.retrbinary("RETR " + filename ,open(filename, 'wb').write)
    except:
        print "Error"

ftp = ftplib.FTP("ftp.nluug.nl")
ftp.login("anonymous", "ftplib-example-1")

ftp.cwd('/pub/')          change directory to /pub/
getFile(ftp,'README.nluug')

ftp.quit()

当运行上述程序时，发现文件README.nlug存在于启动连接的本地系统中。

读取数据

在以下示例中，使用模块urllib2读取数据的必需部分，可以将其复制并保存到本地系统中。
当我们运行上面的程序时，得到以下输出 -

import urllib2
response = urllib2.urlopen('http://www.yiibai.com/python')
html = response.read(200)
print html

执行上面示例代码，得到类似以下结果：

<!DOCTYPE html>
<!--[if IE 8]><html class="ie ie8"> <![endif]-->
<!--[if IE 9]><html class="ie ie9"> <![endif]-->
<!--[if gt IE 9]><!-->  <html> <!--<![endif]-->
<head>
<!-- Basic -->
<meta charset="ut

Python连接重用

原文：https://www.yiibai.com/python_network_programming/python_connection_re_use.html

当客户端向服务器发出有效请求时，它们之间将建立一个临时连接以完成发送和接收过程。但是在某些情况下，由于正在通信的程序之间需要自动请求和响应，因此需要保持连接状态。以一个交互式网页为例。加载网页后，需要提交表单数据或下载其他CSS和JavaScript组件。需要保持连接状态以提高性能，并在客户端和服务器之间保持不间断的通信。

Python提供了urllib3模块，该模块具有一些方法来处理客户端和服务器之间的连接重用。在下面的示例中，我们通过在GET请求中传递不同的参数来创建连接并发出多个请求。我们收到了多个响应，但我们还计算了该过程中已使用的连接数。如我们所见，连接数没有改变，这意味着连接的重用。

from urllib3 import HTTPConnectionPool

pool = HTTPConnectionPool('ajax.googleapis.com', maxsize=1)
r = pool.request('GET', '/ajax/services/search/web',
                 fields={'q': 'python', 'v': '1.0'})
print 'Response Status:', r.status

# Header of the response
print 'Header: ',r.headers['content-type']

# Content of the response
print 'Python: ',len(r.data)

r = pool.request('GET', '/ajax/services/search/web',
             fields={'q': 'php', 'v': '1.0'})

# Content of the response
print 'php: ',len(r.data)

print 'Number of Connections: ',pool.num_connections

print 'Number of requests: ',pool.num_requests

当执行上面示例代码，得到以下结果：

Response Status: 200
Header:  text/javascript; charset=utf-8
Python:  211
php:  211
Number of Connections:  1
Number of requests:  2

Python网络接口

原文：https://www.yiibai.com/python_network_programming/python_network_interface.html

当在一台机器上有多个接口时，需要跟踪它们的名称，状态等。在Python中，可以列出接口及其状态。

示例

在下面的示例中，使用python模块netifaces，它提供了接口及其状态的详细信息。使用的方法非常简单直接。

import netifaces

print (netifaces.interfaces())

print (netifaces.ifaddresses('lo'))

print (netifaces.AF_LINK)

addrs = netifaces.ifaddresses('ens33')
print(addrs[netifaces.AF_INET])

print(addrs[netifaces.AF_LINK])

执行上面示例代码，得到以下结果：

# Result

['lo', 'ens33']
{17: [{'peer': '00:00:00:00:00:00', 'addr': '00:00:00:00:00:00'}], 2: [{'peer': '127.0.0.1', 'addr': '127.0.0.1', 'netmask': '255.0.0.0'}], 10: [{'addr': '::1', 'netmask': 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128'}]}

17

[{'netmask': '255.255.255.0', 'addr': '192.168.1.128', 'broadcast': '192.168.1.255'}]
[{'addr': '0a:0c:21:aa:21:0a', 'broadcast': 'ff:ff:ff:ff:ff:ff'}]

Python Socket程序

原文：https://www.yiibai.com/python_network_programming/python_sockets_programming.html

Python提供了对网络服务的两个访问级别。在较低的级别上，可以访问底层操作系统中的基本套接字支持，从而可以为面向连接和无连接的协议实现客户端和服务器。

Python还具有提供对特定应用程序级网络协议(例如FTP，HTTP等)的更高级别访问的库。

套接字是双向通信通道的端点。套接字可以在一个进程内，同一台机器上的进程之间或不同大陆上的进程之间进行通信。在python中使用套接字模块来创建和使用套接字。

套接字有自己的词汇表 -

编号 | 术语 | 描述
1 | Domain | 用作传输机制的协议系列。这些值是常量，例如：AF_INET，PF_INET，PF_UNIX，PF_X25等。
2 | type | 两个端点之间的通信类型，通常是面向连接协议的SOCK_STREAM和无连接协议的SOCK_DGRAM。
3 | protocol | 通常为零，可用于标识域和类型内协议的变体。
4 | hostname | 网络接口的标识符
5 | port | 每台服务器侦听在一个或多个端口上调用的客户端。端口可以是Fixnum端口号，包含端口号的字符串或服务名称。

Socket模块

要创建套接字，必须使用套接字模块中可用的socket.socket()函数，该函数具有以下常规语法：

s = socket.socket (socket_family, socket_type, protocol=0)

这是参数的描述-

socket_family - 如前所述，它是AF_UNIX或AF_INET。

socket_type - 它是SOCK_STREAM或SOCK_DGRAM。

protocol - 通常忽略，默认为0。

一旦有了套接字对象，就可以使用所需的函数来创建客户端或服务器程序。

服务器套接字方法

编号 | 方法 | 描述
1 | s.bind() | 此方法将地址(主机名，端口号对)绑定到套接字。
2 | s.listen() | 此方法设置并启动TCP侦听器。
3 | s.accept() | 这被动地接受TCP客户端连接，等待连接到达(阻塞)。

客户端套接字方法

编号 | 方法 | 描述
1 | s.connect() | 此方法主动启动TCP服务器连接。

通用套接字方法

编号 | 方法 | 描述
1 | s.recv() | 该方法接收TCP消息
2 | s.send() | 该方法传输TCP消息
3 | s.recvfrom() | 此方法接收UDP消息
4 | s.sendto() | 此方法传输UDP消息
5 | s.close() | 此方法关闭套接字
6 | socket.gethostname() | 返回主机名称。

简单的服务器

要编写Internet服务器，我们使用套接字模块中可用的套接字函数来创建套接字对象。然后使用套接字对象调用其他函数来设置套接字服务器。

现在调用bind(hostname，port)函数为给定主机上的服务指定一个端口。接下来，调用返回对象的accept方法。此方法将一直等到客户端连接到您指定的端口，然后返回表示该客户端连接的连接对象。

#!/usr/bin/python           # This is server.py file

import socket               # Import socket module

s = socket.socket()         # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12345                # Reserve a port for your service.
s.bind((host, port))        # Bind to the port

s.listen(5)                 # Now wait for client connection.
while True:
   c, addr = s.accept()     # Establish connection with client.
   print 'Got connection from', addr
   c.send('Thank you for connecting')
   c.close()                # Close the connection

简单的客户端

让我们编写一个非常简单的客户端程序，该程序打开到给定端口12345和给定主机的连接。使用Python的套接字模块函数创建套接字客户端非常简单。

socket.connect(hosname，port)在端口上打开到主机名的TCP连接。打开套接字后，可以像读取任何IO对象一样从中读取套接字。完成后，记得关闭它，就像关闭文件一样。

以下代码是一个非常简单的客户端，该客户端连接到给定的主机和端口，从套接字读取任何可用数据，然后退出-

#!/usr/bin/python           # This is client.py file

import socket               # Import socket module

s = socket.socket()         # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12345                # Reserve a port for your service.

s.connect((host, port))
print s.recv(1024)
s.close                     # Close the socket when done

在后台运行此server.py，然后在client.py上方运行以查看结果。

# Following would start a server in background.
$ python server.py &

# Once server is started run client as follows:
$ python client.py

将产生以下结果 -

Got connection from ('127.0.0.1', 48437)
Thank you for connecting

公开网址的套接字

在下面的示例中，使用套接字模块中的几种方法来查找服务器的地址信息和主机名详细信息。

import socket
from pprint import pprint

# get server address
addrinfo = socket.getaddrinfo('yiibai.com', 'www')

pprint(addrinfo)

# get server hostname
print socket.gethostname()

执行上面示例代码，得到以下结果：

[(2, 1, 0, '', ('213.130.81.5', 80))]
DESKTOP-MAXSU

Python HTTP客户端

原文：https://www.yiibai.com/python_network_programming/python_http_client.html

在http协议中，来自客户端的请求到达服务器，并假定它是有效请求，并获取一些数据和元数据。可以使用python请求模块中提供的各种功能来分析服务器的响应。下面的python程序在客户端运行，并显示服务器发送的响应结果。

取得初步响应

在下面的程序中，requests模块的get方法从服务器获取数据，并以纯文本格式打印。

import requests
r = requests.get('https://httpbin.org/')
print(r.text)[:200]

当运行上面的程序时，得到以下输出-

<!DOCTYPE html >
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>httpbin.org</title>
  <link
href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+

获取会话对象响应

通过Session对象，可以在请求中保留某些参数。它还会在会话实例发出的所有请求中保留cookie。如果要向同一主机发出多个请求，则基础TCP连接将被重用。

import requests
s = requests.Session()

s.get('http://httpbin.org/cookies/set/sessioncookie/yyyxxxx1425')
r = s.get('http://httpbin.org/cookies')

print(r.text)

运行上面示例代码，得到以下结果：

{"cookies":{"sessioncookie":"yyyxxxx1425"}}

处理错误

如果由于服务器处理请求时出现问题而引起一些错误，则python程序可以使用timeout参数正常处理引发的异常，如下所示。程序将等待超时错误的定义值，然后引发超时错误。

requests.get('http://github.com', timeout=10.001)

Python HTTP服务器

原文：https://www.yiibai.com/python_network_programming/python_http_server.html

Python标准库带有内置的网络服务器，可以调用该服务器以进行简单的Web客户端服务器通信。可以通过程序分配端口号，并可以通过该端口访问Web服务器。尽管它不是可以解析多种文件的功能齐全的Web服务器，但它可以解析简单的静态html文件并通过使用所需的响应代码对其进行响应来提供服务。

下面的程序启动一个简单的Web服务器，并在端口8001上打开它。服务器的成功运行由响应代码200指示，如程序输出所示。

import SimpleHTTPServer
import SocketServer

PORT = 8001

Handler = SimpleHTTPServer.SimpleHTTPRequestHandler

httpd = SocketServer.TCPServer(("", PORT), Handler)

print "serving at port", PORT
httpd.serve_forever()

运行上面示例代码，得到以下结果：

serving at port 8001
127.0.0.1 - - [14/Jun/2019 09:34:12] "GET / HTTP/1.1" 200 -

服务本地主机

如果决定将python服务器作为仅服务于本地主机的本地主机，则可以使用以下程序来实现。

import sys
import BaseHTTPServer
from SimpleHTTPServer import SimpleHTTPRequestHandler

HandlerClass = SimpleHTTPRequestHandler
ServerClass  = BaseHTTPServer.HTTPServer
Protocol     = "HTTP/1.0"

if sys.argv[1:]:
    port = int(sys.argv[1])
else:
    port = 8000
server_address = ('127.0.0.1', port)

HandlerClass.protocol_version = Protocol
httpd = ServerClass(server_address, HandlerClass)

sa = httpd.socket.getsockname()
print "Serving HTTP on", sa[0], "port", sa[1], "..."
httpd.serve_forever()

当运行上面的程序时，得到以下输出 -

Serving HTTP on 127.0.0.1 port 8000 ...

Python构建URL

原文：https://www.yiibai.com/python_network_programming/python_building_urls.html

Python requests模块可以帮助构建URLS并动态处理URL值。可以以编程方式获取URL的任何子目录，然后可以用新值替换其中的一部分以构建新的URL。

建立网址

下面的示例使用urljoin在URL路径中获取不同的子文件夹。urljoin方法用于将新值添加到基本URL。

from requests.compat import urljoin
base='https://stackoverflow.com/questions/3764291'
print urljoin(base,'.')
print urljoin(base,'..')
print urljoin(base,'...')
print urljoin(base,'/3892299/')
url_query = urljoin(base,'?vers=1.0')
print url_query
url_sec = urljoin(url_query,'#section-5.4')
print url_sec

执行上面示例代码，得到以下结果：

https://stackoverflow.com/questions/
https://stackoverflow.com/
https://stackoverflow.com/questions/...
https://stackoverflow.com/3892299/
https://stackoverflow.com/questions/3892299?vers=1.0
https://stackoverflow.com/questions/3892299?vers=1.0#section-5.4

分割网址

URL也可以分为多个主要地址。如下所示，使用urlparse方法分隔用于特定查询的附加参数或附加到URL的标记。

from requests.compat import urlparse
url1 = 'https://docs.python.org/2/py-modindex.html#cap-f'
url2='https://docs.python.org/2/search.html?q=urlparse'
print urlparse(url1)
print urlparse(url2)

执行上面示例代码，得到以下结果：

ParseResult(scheme='https', netloc='docs.python.org', path='/2/py-modindex.html', params='', query='', fragment='cap-f')
ParseResult(scheme='https', netloc='docs.python.org', path='/2/search.html', params='', query='q=urlparse', fragment='')

Python Web表单提交

原文：https://www.yiibai.com/python_network_programming/python_webform_submission.html

通常，与网页的交互需要一些数据通过html页面中的表单提交给服务器。这些网络表单通常用于诸如注册新帐户或提供一些信息(例如姓名或卷号)以检索检查结果的过程。requests模块使用带有所需参数的POST方法优雅地处理此问题。

示例

在下面的示例中，我们通过提供用户名和密码值来使用网站的注册表单。提交值后，将打印响应的结果。

import requests

ID_USERNAME = 'signup-user-name'
ID_PASSWORD = 'signup-user-password'
USERNAME = 'username'
PASSWORD = 'yourpassword'
SIGNUP_URL = 'http://codepad.org/login'
def submit_form():
    """Submit a form"""
    payload = {ID_USERNAME : USERNAME, ID_PASSWORD : PASSWORD,}

    resp = requests.get(SIGNUP_URL)
    print "Response to GET request: %s" %resp.content

    resp = requests.post(SIGNUP_URL, payload)
    print "Headers from a POST request response: %s" %resp.headers
#print "HTML Response: %s" %resp.read()

if __name__ == '__main__':
    submit_form()

执行上面示例代码，得到类似下面结果：

Response to GET request: <!DOCTYPE html>
<html>

<head>

    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <meta HTTP-EQUIV="Pragma" CONTENT="no-cache">
    <meta HTTP-EQUIV="Expires" CONTENT="-1">

    <title>Login - codepad</title>

    <link href="/main.css" media="screen" rel="stylesheet" type="text/css" />
    <style type="text/css">

    </style>
    <script src='https://www.google.com/recaptcha/api.js'></script>
    <script>
       function onRecaptcha(token) {
         document.getElementById("editor-form").submit();
       }
    </script>
</head>

    <body >

    .....................
    .....................

Python数据库和SQL

原文：https://www.yiibai.com/python_network_programming/python_databases_and_sql.html

Python编程语言具有用于数据库编程的强大功能。Python支持各种数据库，例如SQLite，MySQL，Oracle，Sybase，PostgreSQL等。Python还支持数据定义语言(DDL)，数据操作语言(DML)和数据查询语句。用于数据库接口的Python标准是Python DB-API。大多数Python数据库接口都遵守该标准。

以下是可用的Python数据库接口的列表：Python数据库接口和API。需要为访问的每个数据库下载单独的DB API模块。

在本章中，我们演示python编程语言连接SQLite数据库。这是通过使用python内置的sqlite3模块完成的。应该首先创建一个代表数据库的连接对象，然后创建一些游标对象以执行SQL语句。

连接到数据库

以下Python代码显示了如何连接到现有数据库。如果数据库不存在，则将创建该数据库，最后将返回一个数据库对象。

#!/usr/bin/python

import sqlite3

conn = sqlite3.connect('test.db')

print "Opened database successfully";

在这里，还可以提供数据库名称作为特殊名称:memory:以在RAM中创建数据库。现在，我们运行上面的程序在当前目录中创建数据库test.db。可以根据需要更改路径，将上面的代码保存在sqlite.py文件中，并如下所示执行它。如果成功创建了数据库，则它将显示以下消息。

$chmod +x sqlite.py
$./sqlite.py
Open database successfully

创建表

以下Python程序将用于在先前创建的数据库中创建表。

#!/usr/bin/python

import sqlite3

conn = sqlite3.connect('test.db')
print "Opened database successfully";

conn.execute('''CREATE TABLE COMPANY
         (ID INT PRIMARY KEY     NOT NULL,
         NAME           TEXT    NOT NULL,
         AGE            INT     NOT NULL,
         ADDRESS        CHAR(50),
         SALARY         REAL);''')
print "Table created successfully";

conn.close()

执行上述程序后，它将在test.db中创建COMPANY表，并显示以下消息-

Opened database successfully
Table created successfully

插入操作

以下Python程序显示了如何在上面的示例中创建的COMPANY表中创建记录。

#!/usr/bin/python

import sqlite3

conn = sqlite3.connect('test.db')
print "Opened database successfully";

conn.execute("INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) \
      VALUES (1, 'Paul', 32, 'California', 19000.00 )");

conn.execute("INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) \
      VALUES (2, 'Allen', 25, 'Texas', 19800.00 )");

conn.execute("INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) \
      VALUES (3, 'Teddy', 23, 'Norway', 22000.00 )");

conn.execute("INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) \
      VALUES (4, 'Mark', 25, 'Rich-Mond ', 55000.00 )");

conn.commit()
print "Records created successfully";
conn.close()

执行上述程序后，它将在COMPANY表中创建给定记录，并将显示以下两行-

Opened database successfully
Records created successfully

选择操作

以下Python程序演示了如何从上例中创建的COMPANY表中查询获取并显示记录。

#!/usr/bin/python

import sqlite3

conn = sqlite3.connect('test.db')
print "Opened database successfully";

cursor = conn.execute("SELECT id, name, address, salary from COMPANY")
for row in cursor:
   print "ID = ", row[0]
   print "NAME = ", row[1]
   print "ADDRESS = ", row[2]
   print "SALARY = ", row[3], "\n"

print "Operation done successfully";
conn.close()

执行上述程序时，将产生以下结果 -

Opened database successfully
ID = 1
NAME = Paul
ADDRESS = California
SALARY = 20000.0

ID = 2
NAME = Allen
ADDRESS = Texas
SALARY = 15000.0

ID = 3
NAME = Teddy
ADDRESS = Norway
SALARY = 20000.0

ID = 4
NAME = Mark
ADDRESS = Rich-Mond
SALARY = 65000.0

Operation done successfully

更新操作

以下Python代码显示了如何使用UPDATE语句更新任何记录，然后从COMPANY表中查询获取并显示更新的记录。

#!/usr/bin/python

import sqlite3

conn = sqlite3.connect('test.db')
print "Opened database successfully";

conn.execute("UPDATE COMPANY set SALARY = 25000.00 where ID = 1")
conn.commit
print "Total number of rows updated :", conn.total_changes

cursor = conn.execute("SELECT id, name, address, salary from COMPANY")
for row in cursor:
   print "ID = ", row[0]
   print "NAME = ", row[1]
   print "ADDRESS = ", row[2]
   print "SALARY = ", row[3], "\n"

print "Operation done successfully";
conn.close()

执行上述程序时，将产生以下结果 -

Opened database successfully
Total number of rows updated : 1
ID = 1
NAME = Paul
ADDRESS = California
SALARY = 25000.0

ID = 2
NAME = Allen
ADDRESS = Texas
SALARY = 15000.0

ID = 3
NAME = Teddy
ADDRESS = Norway
SALARY = 20000.0

ID = 4
NAME = Mark
ADDRESS = Rich-Mond
SALARY = 65000.0

Operation done successfully

删除操作

以下Python代码显示了如何使用DELETE语句删除任何记录，然后从COMPANY表中查询获取并显示其余记录。

#!/usr/bin/python

import sqlite3

conn = sqlite3.connect('test.db')
print "Opened database successfully";

conn.execute("DELETE from COMPANY where ID = 2;")
conn.commit()
print "Total number of rows deleted :", conn.total_changes

cursor = conn.execute("SELECT id, name, address, salary from COMPANY")
for row in cursor:
   print "ID = ", row[0]
   print "NAME = ", row[1]
   print "ADDRESS = ", row[2]
   print "SALARY = ", row[3], "\n"

print "Operation done successfully";
conn.close()

执行上述程序时，将产生以下结果 -

Opened database successfully
Total number of rows deleted : 1
ID = 1
NAME = Paul
ADDRESS = California
SALARY = 20000.0

ID = 3
NAME = Teddy
ADDRESS = Norway
SALARY = 20000.0

ID = 4
NAME = Mark
ADDRESS = Rich-Mond
SALARY = 65000.0

Operation done successfully

Python Telnet

原文：https://www.yiibai.com/python_network_programming/python_telnet.html

Telnet是一种网络协议，它允许一台计算机上的用户登录到另一台也属于同一网络的计算机。telnet命令与主机名一起使用，然后输入用户凭据。成功登录后，远程用户可以以类似于系统普通用户的方式访问应用程序和数据。当然，某些权限是由设置和维护系统的系统管理员控制。

在Python中，telnet由telnetlib模块实现，该模块具有Telnet类，该类具有建立连接所需的方法。在下面的示例中，使用getpass模块在登录过程中处理密码提示。另外，假设已建立到UNIX主机的连接。下面说明程序中使用的telnetlib.Telnet类的各种方法。

Telnet.read_until - 读取直到遇到给定的预期字符串或超时秒数为止。

Telnet.write - 将字符串写入套接字，将所有IAC字符加倍。如果连接被阻止，则可能会阻止。如果关闭连接，可能会引发socket.error。

Telnet.read_all()-读取所有数据，直到EOF；阻塞直到连接关闭。

示例

import getpass
import telnetlib

HOST = "http://localhost:8000/"
user = raw_input("Enter your remote account: ")
password = getpass.getpass()

tn = telnetlib.Telnet(HOST)

tn.read_until("login: ")
tn.write(user + "\n")
if password:
    tn.read_until("Password: ")
    tn.write(password + "\n")

tn.write("ls\n")
tn.write("exit\n")

print tn.read_all()

运行上面示例代码，得到以下结果：

 - lrwxrwxrwx    1 0        0               1 Nov 13  2012 ftp -> .
- lrwxrwxrwx    1 0        0               3 Nov 13  2012 mirror -> pub
- drwxr-xr-x   23 0        0            4096 Nov 27  2017 pub
- drwxr-sr-x   88 0        450          4096 May 04 19:30 site
- drwxr-xr-x    9 0        0            4096 Jan 23  2014 vol

请注意，此输出由运行程序时提交详细信息的远程计算机决定。

Python电子邮件

原文：https://www.yiibai.com/python_network_programming/python_email_messages.html

电子邮件是一项服务，它使我们可以通过互联网以电子方式发送消息。它提供了一种在人们之间分发信息的高效，廉价且实时的方式。

电子邮件地址

每个电子邮件用户都为其电子邮件帐户分配了唯一的名称。此名称称为电子邮件地址。不同的用户可以根据电子邮件地址发送和接收消息。
电子邮件通常采用username@domainname的形式。例如，webmaster@yiibai.com是一个电子邮件地址，其中webmaster是用户名，而yiibai.com是域名。

用户名和域名之间用@符号分隔。

电子邮件地址不区分大小写。

电子邮件地址中不允许有空格。

电子邮件的前五行称为电子邮件标题。标头部分包含以下字段：

From - 此字段表示发件人的地址，即发送电子邮件的人。

Date - 此字段指示发送电子邮件的日期。

To - 此字段指示收件人的地址，即电子邮件发送给的收件人。

Subject - 此字段指示电子邮件的用途。它应该是准确的，并指向重点。

CC - CC代表复本。它包括要及时通知的收件人地址，但不完全是预期的收件人。

BCC - 当不希望一个或多个收件人知道在邮件上复制了其他人时使用它。

Greeting - 问候语是实际信息的开头。例如。嗨，先生或嗨，大家好！

Text - 它代表消息的实际内容。

Signature - 这是电子邮件的最后一部分。它包括发件人姓名，地址和联系电话。

Python具有EmailMessage类，可用于构建电子邮件。此类是自定义电子邮件消息不同部分(如TO和FROM标记，主题行以及电子邮件内容)所需的方法。

　示例

在下面的示例中，我们将创建一封电子邮件，其中包含电子邮件的所有必要部分。当打印出消息的内容，我们就可以看到完整的电子邮件。

import email.message, email.policy, email.utils, sys
text = """Welcome to Yiibai - Simple Easy Learning"""

message = email.message.EmailMessage(email.policy.SMTP)
message['To'] = 'you@yourdomain.com'
message['From'] = 'Learn '
message['Subject'] = 'A mail To you'
message['Date'] = email.utils.formatdate(localtime=True)
message['Message-ID'] = email.utils.make_msgid()
message.set_content(text)
sys.stdout.buffer.write(message.as_bytes())

执行上面示例代码，得到以下结果：

To: you@yourdomain.com
From: Learn
Subject: A mail To you
Date: Wed, 13 Jun 2018 06:51:09 -0700
Message-ID: <152xxxx976.4xx6.5xxx5026x0802709@ubuntu>
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 7bit
MIME-Version: 1.0

Welcome to Yiibai - Simple Easy Learning

Python SMTP

原文：https://www.yiibai.com/python_network_programming/python_smtp.html

简单邮件传输协议(SMTP)是一种协议，用于处理在电子邮件服务器之间发送电子邮件和路由电子邮件。
Python提供了smtplib模块，该模块定义了一个SMTP客户端会话对象，该对象可用于将邮件发送到具有SMTP或ESMTP侦听器守护程序的任何Internet计算机。

SMTP对象具有一个称为sendmail的实例方法，该方法通常用于完成邮件的发送工作。它需要三个参数-

sender- 具有发件人地址的字符串。

receivers- 字符串列表，每个接收者一个。

message- 以各种RFC中指定的格式格式化为字符串的消息。

Python SMTP示例

这是使用Python脚本发送一封电子邮件的简单方法。示例代码：

#!/usr/bin/python3

import smtplib

sender = 'from@fromdomain.com'
receivers = ['to@todomain.com']

message = """From: From Person <from@fromdomain.com>
To: To Person <to@todomain.com>
Subject: SMTP e-mail test

This is a test e-mail message.
"""

try:
   smtpObj = smtplib.SMTP('localhost')
   smtpObj.sendmail(sender, receivers, message)
   print "Successfully sent email"
except SMTPException:
   print "Error: unable to send email"

在这里，已经在邮件中放置了一个基本电子邮件，使用三重引号，请注意正确设置标题的格式。电子邮件需要一个“发件人”，“收件人”和“主题”标头，并以空白行与电子邮件正文分开。

要发送邮件，需要使用smtpObj连接到本地计算机上的SMTP服务器。然后，调用sendmail方法与消息，发件人地址和目标地址一起用作参数(即使发件人和收件人地址位于电子邮件本身之内，但它们并不总是用于路由邮件)。

如果您不在本地计算机上运行SMTP服务器，则可以使用smtplib客户端与远程SMTP服务器通信。除非您使用Webmail服务(例如gmail或Yahoo! Mail)，否则您的电子邮件提供商必须已向您提供了可以提供它们的外发邮件服务器详细信息，如下所示-

mail = smtplib.SMTP('smtp.gmail.com', 587)

使用Python发送HTML电子邮件

当使用Python发送文本消息时，所有内容均被视为简单文本。即使您在文本消息中包含HTML标签，它也将显示为简单文本，并且HTML标签不会根据HTML语法进行格式化。但是，Python提供了将HTML消息作为实际HTML消息发送的选项。

发送电子邮件时，可以指定Mime版本，内容类型和字符集来发送HTML电子邮件。

示例代码
以下是将HTML内容作为电子邮件发送的示例 -

#!/usr/bin/python3

import smtplib

message = """From: From Person <from@fromdomain.com>
To: To Person <to@todomain.com>
MIME-Version: 1.0
Content-type: text/html
Subject: SMTP HTML e-mail test

This is an e-mail message to be sent in HTML format

<b>This is HTML message.</b>
<h1>This is headline.</h1>
"""

try:
   smtpObj = smtplib.SMTP('localhost')
   smtpObj.sendmail(sender, receivers, message)
   print "Successfully sent email"
except SMTPException:
   print "Error: unable to send email"

Python POP3

原文：https://www.yiibai.com/python_network_programming/python_pop3.html

pop3协议是用于从电子邮件服务器下载邮件信息的电子邮件协议。这些消息可以存储在本地计算机中。

关键点

POP是应用程序层互联网标准协议。

由于POP支持脱机访问邮件，因此需要较少的Internet使用时间。

POP不允许搜索功能。

为了访问消息，有必要下载它们。

它仅允许在服务器上创建一个邮箱。

它不适用于访问非邮件数据。

POP命令通常缩写为三个或四个字母的代码。例如 - STAT。

POP命令

下表描述了一些POP命令：

编号 | 命令 | 描述
1 | LOGIN | 此命令用于打开连接。
2 | STAT | 此命令用于显示邮箱中当前的邮件数。
3 | LIST | 它用于获取消息摘要，其中显示每个消息摘要。
4 | RETR | 此命令用于选择一个邮箱来访问邮件。
5 | DELE | 此命令用于删除消息。
6 | RSET | 此命令用于将会话重置为其初始状态。
7 | QUIT | 此命令用于注销会话。

Pyhton的poplib模块提供了名为pop和pop3_SSL的类，用于满足这一要求。我们提供主机名和端口号作为参数。在以下示例中，我们连接到gmail服务器，并在提供登录凭据后检索消息。

import  poplib

user = 'username'
# Connect to the mail box
Mailbox = poplib.POP3_SSL('pop.googlemail.com', '995')
Mailbox.user(user)
Mailbox.pass_('password')
NumofMessages = len(Mailbox.list()[1])
for i in range(NumofMessages):
    for msg in Mailbox.retr(i+1)[1]:
        print msg
Mailbox.quit()

当运行上述程序时，将检索消息。

Python IMAP

原文：https://www.yiibai.com/python_network_programming/python_imap.html

IMAP是一种电子邮件检索协议，它不下载电子邮件。它只是读取并显示它们。这在低带宽条件下非常有用。Python的客户端库imaplib用于通过imap协议访问电子邮件。

IMAP代表Internet邮件访问协议。它于1986年首次提出。

关键点：

IMAP允许客户端程序在服务器上处理电子邮件，而无需在本地计算机上下载它们。

电子邮件由远程服务器保留和维护。

它能够执行任何操作，例如下载，删除邮件而不读取邮件。它能够创建，操作和删除称为邮箱的远程消息文件夹。

IMAP使用户可以搜索电子邮件。

它允许并发访问多个邮件服务器上的多个邮箱。

IMAP命令
下表描述了一些IMAP命令：

编号 | 命令 | 描述说明
1 | IMAP_LOGIN | 此命令用于打开连接。
2 | CAPABILITY | 此命令用于要求列出服务器支持的功能。
3 | NOOP | 此命令用于在不活动期间用作新消息或消息状态更新的定期轮询。
4 | SELECT | 此命令用于选择一个邮箱来访问邮件。
5 | EXAMINE | 此命令与SELECT命令相同，除了不允许更改邮箱。
6 | CREATE | 此命令用于创建具有指定名称的邮箱。
7 | DELETE | 此命令用于永久删除具有给定名称的邮箱。
8 | RENAME | 此命令用于更改邮箱的名称。
9 | LOGOUT | 此命令通知服务器客户端已完成会话。服务器必须在OK响应之前发送BYE未加标签的响应，然后关闭网络连接。

示例

在以下示例中，使用用户凭据登录到Gmail服务器。然后，选择在收件箱中显示消息。for循环用于逐个显示获取的消息，最后关闭连接。

import imaplib
import pprint

imap_host = 'imap.gmail.com'
imap_user = 'username@gmail.com'
imap_pass = 'password'

# connect to host using SSL
imap = imaplib.IMAP4_SSL(imap_host)

## login to server
imap.login(imap_user, imap_pass)

imap.select('Inbox')

tmp, data = imap.search(None, 'ALL')
for num in data[0].split():
    tmp, data = imap.fetch(num, '(RFC822)')
    print('Message: {0}\n'.format(num))
    pprint.pprint(data[0][1])
    break
imap.close()

根据邮箱配置，显示邮件。

Python SSH

原文：https://www.yiibai.com/python_network_programming/python_ssh.html

SSH或安全套接字Shell，是一种网络协议，提供了一种访问远程计算机的安全方式。Secure Shell在通过不安全网络(例如Internet)连接的两台计算机之间提供了强大的身份验证和安全的加密数据通信。SSH被网络管理员广泛地用于远程管理系统和应用程序，从而使他们可以通过网络登录到另一台计算机，执行命令以及将文件从一台计算机移动到另一台计算机。

随着云服务器的价格越来越便宜，SSH是在云服务器上执行各种任务的最常用工具。可以用它来：

为客户的网站设置Web服务器

将源代码部署到生产服务器

在python中，SSH是通过使用称为fabric的python库实现的。它可用于通过SSH远程发出命令。

示例

在下面的示例中，我们连接到主机并发出命令以标识主机类型。捕获结果并将其显示为带格式的文本。

from fabric import Connection
result = Connection('xyz.com').run('uname -s')
msg = "Ran {.command!r} on {.connection.host}, got stdout:\n{.stdout}"
print(msg.format(result))

运行上面代码得到以下结果：

Linux

这是一个示例结果，将取决于服务器系统的版本。

Python FTP

原文：https://www.yiibai.com/python_network_programming/python-ftp.html

FTP或文件传输协议是一种众所周知的网络协议，用于在网络中的计算机之间传输文件。它是在客户端服务器体系结构上创建的，可以与用户身份验证一起使用。也可以在不进行身份验证的情况下使用它，但这将降低安全性。FTP连接保持当前的工作目录和其他标志，并且每次传输都需要一个辅助连接，通过该连接可以传输数据。大多数常见的Web浏览器都可以检索FTP服务器上托管的文件。

1. FTP类中的方法

在python中，我们使用ftplib模块，该模块具有以下必需的方法来列出文件，因为需要使用FTP来传输文件。

方法 | 描述
pwd() | 当前工作目录。
cwd() | 将当前工作目录更改为指定路径。
dir([path[,...[,cb]]) | 显示路径的目录列表。传递给retrlines()的可选回调cb。
storlines(cmd, f) | 使用给定的FTP cmd上传文本文件-例如STOR文件名。
storbinary(cmd,f[, bs=8192]) | 与storlines()类似，但用于二进制文件。
delete(path) | 删除指定路径下的远程文件。
mkd(directory) | 创建远程目录。
exception ftplib.error_temp | 当收到表示临时错误的错误代码(响应代码在400-499范围内)时，引发异常。
exception ftplib.error_perm | 当收到表示永久错误的错误代码(响应代码在500–599范围内)时，引发异常。
connect(host[, port[, timeout]]) | 连接到给定的主机和端口。默认端口号是21，由FTP协议指定。
quit() | 关闭连接并退出。

以下是上述某些方法的示例。

2. 列出文件

下面的示例使用匿名登录ftp服务器并列出当前目录的内容。它处理文件和目录的名称，并将它们存储为列表。然后将它们打印出来。

import ftplib

ftp = ftplib.FTP("ftp.nluug.nl")
ftp.login("anonymous", "ftplib-example-1")

data = []

ftp.dir(data.append)

ftp.quit()

for line in data:
    print "-", line

执行上面示例代码，得到以下结果：

- lrwxrwxrwx    1 0        0               1 Nov 13  2012 ftp -> .
- lrwxrwxrwx    1 0        0               3 Nov 13  2012 mirror -> pub
- drwxr-xr-x   23 0        0            4096 Nov 27  2017 pub
- drwxr-sr-x   88 0        450          4096 May 04 19:30 site
- drwxr-xr-x    9 0        0            4096 Jan 23  2014 vol

3. 更改目录

下面的程序使用ftplib模块中可用的cwd方法来更改目录，然后获取所需的内容。

import ftplib

ftp = ftplib.FTP("ftp.nluug.nl")
ftp.login("anonymous", "ftplib-example-1")

data = []

ftp.cwd('/pub/')          change directory to /pub/
ftp.dir(data.append)

ftp.quit()

for line in data:
    print "-", line

执行上面示例代码，得到以下结果：

- lrwxrwxrwx    1 504      450            14 Nov 02  2007 FreeBSD -> os/BSD/FreeBSD
- lrwxrwxrwx    1 504      450            20 Nov 02  2007 ImageMagick -> graphics/ImageMagick
- lrwxrwxrwx    1 504      450            13 Nov 02  2007 NetBSD -> os/BSD/NetBSD
- lrwxrwxrwx    1 504      450            14 Nov 02  2007 OpenBSD -> os/BSD/OpenBSD
- -rw-rw-r--    1 504      450           932 Jan 04  2015 README.nluug
- -rw-r--r--    1 504      450          2023 May 03  2005 WhereToFindWhat.txt
- drwxr-sr-x    2 0        450          4096 Jan 26  2008 av
- drwxrwsr-x    2 0        450          4096 Aug 12  2004 comp

4. 提取文件

如上所示获取文件列表后，可以使用getfile方法获取特定文件。此方法将文件的副本从远程系统移动到启动ftp连接的本地系统。

import ftplib
import sys

def getFile(ftp, filename):
    try:
        ftp.retrbinary("RETR " + filename ,open(filename, 'wb').write)
    except:
        print "Error"

ftp = ftplib.FTP("ftp.nluug.nl")
ftp.login("anonymous", "ftplib-example-1")

ftp.cwd('/pub/')          change directory to /pub/
getFile(ftp,'README.nluug')

ftp.quit()

当运行上述程序时，就会发现文件README.nlug存在于启动连接的本地系统中。

Python SFTP

原文：https://www.yiibai.com/python_network_programming/python-sftp.html

FTP也称为SSH文件传输协议。它是一种网络协议，可通过任何可靠的数据流提供文件访问，文件传输和文件管理。该程序通过安全通道(例如SSH)运行，服务器已对客户端进行身份验证，并且该协议可使用客户端用户的身份。

pysftp模块是SFTP的简单接口。该模块提供高级抽象和基于任务的例程来处理SFTP需求。使用以下命令将模块安装到python环境中。

pip install pysftp

示例

在下面的示例中，使用sftp登录到远程服务器，然后获取在指定目录中放置一些文件。

import pysftp

with pysftp.Connection('hostname', username='me', password='secret') as sftp:

    with sftp.cd('/allcode'):           # temporarily chdir to allcode
        sftp.put('/pycode/filename')      # upload file to allcode/pycode on remote
        sftp.get('remote_file')         # get a remote file

当运行上面的代码时，可以看到allcode目录中存在的文件列表，还可以在指定目录中放置或获取一些文件。

Python Web服务器

原文：https://www.yiibai.com/python_network_programming/python-web-servers.html

Python具有足够的通用性，可以创建许多类型的应用程序和驱动互联网或其他计算机网络的程序。互联网的一个重要方面是位于客户端服务器模型根源的Web服务器。在本章中，我们来看看如何使用纯Python语言创建Web服务器。

1. Gunicorn

Gunicorn是一个独立的Web服务器，具有中央主进程，进程负责管理不同类型的启动的工作进程。这些工作进程直接处理并处理请求。所有这些都可以进行配置和调整，以适应生产方案的各种需求。

服务器，web2py等。

提供各种工人类型/配置和自动工人过程管理的选择。

通过同步和异步工作程序支持HTTP/1.0和HTTP/1.1(保持活动)。

带有SSL支持。

带挂钩可扩展。

2. CherryPy WSGI服务器

CherryPy是一个自包含的Web框架，因为它可以独立运行，而无需其他软件。它具有自己的WSGI，HTTP/1.1兼容的Web服务器。由于它是WSGI服务器，因此它也可以用于服务任何其他WSGI Python应用程序，而不必局限于CherryPy的应用程序开发框架。

重要功能

它可以运行在WSGI上运行的任何Python Web应用程序。

它可以处理静态文件，并且只能用于单独提供文件和文件夹。

它是线程池。

它带有对SSL的支持。

它是一种易于适应，易于使用的纯Python替代方案，具有健壮性和可靠性。

3. Twisted Web

Twisted Web是Twisted网络库随附的Web服务器。Twisted本身是“事件驱动的网络引擎”，而Twisted Web服务器则在WSGI上运行，并且能够驱动其他Python Web应用程序。

重要功能

它运行WSGI Python应用程序。

它可以像Python Web服务器框架一样工作，使用Python语言对其编程，以实现自定义HTTP服务。

它通过在HTTP请求上执行的Python Scrips(.rpy)提供简单快速的原型制作功能。

它具有代理和反向代理功能。

它支持虚拟主机。

它甚至可以服务于Perl，PHP等。

Python上传数据

原文：https://www.yiibai.com/python_network_programming/python_uploading_data.html

可以使用处理ftp或文件传输协议的python模块将数据上传到服务器。
需要安装模块ftplib才能实现上面功能。

pip install ftplib

1. 使用ftplib

在下面的示例中，使用FTP方法连接到服务器，然后提供用户凭据。接下来，我们提到文件的名称以及在服务器中发送和存储文件的storbinary方法。

import ftplib

ftp = ftplib.FTP("127.0.0.1")
ftp.login("username", "mypassword")
file = open('index.html','rb')
ftp.storbinary("STOR " + file, open(file, "rb"))
file.close()
ftp.quit()

当运行上述程序时，我们观察到该文件的副本已在服务器中创建。

2. 使用ftpreety

与ftplib相似，可以使用ftpreety安全地连接到远程服务器并上传文件。可以使用ftpreety下载文件。下面的程序相象相同。

from ftpretty import ftpretty

# Mention the host
host = "127.0.0.1"

# Supply the credentisals
f = ftpretty(host, user, pass )

# Get a file, save it locally
f.get('someremote/file/on/server.txt', '/tmp/localcopy/server.txt')

# Put a local file to a remote location
# non-existent subdirectories will be created automatically
f.put('/tmp/localcopy/data.txt', 'someremote/file/on/server.txt')

当运行上述程序时，可以看到该文件的副本已在服务器中创建。

Python代理服务器

原文：https://www.yiibai.com/python_network_programming/python_proxy_server.html

代理服务器用于通过另一台服务器浏览到某些网站，以便浏览保持匿名。它也可以用来绕过特定IP地址的阻止。

我们通过传递代理服务器地址作为参数，使用urllib模块中的urlopen方法访问网站。

示例
在下面的示例中，使用代理地址访问网站twitter.com进行匿名访问。OK的响应状态证明已成功通过代理服务器访问。

import urllib
URL = 'http://www.xntutor.com'
PROXY_ADDRESS = "202.54.11.6:8088"
if __name__ == '__main__':
    resp = urllib.urlopen(URL, proxies = {"http" : PROXY_ADDRESS})
print "Proxy server returns response headers: %s " %resp.headers

当运行上面的程序时，得到类似以下输出-

Proxy server returns response headers: cache-control: no-cache, no-store, must-revalidate, pre-check=0, post-check=0
content-length: 185960
content-type: text/html;charset=utf-8
date: Mon, 02 Jul 2019 02:06:19 GMT
expires: Tue, 31 Mar 1981 05:00:00 GMT
last-modified: Mon, 02 Jul 2019 02:06:19 GMT
pragma: no-cache
server: tsa_n
set-cookie: fm=0; Expires=Mon, 02 Jul 2019 02:06:10 GMT; Path=/; Domain=.twitter.com; Secure; HTTPOnly
set-cookie:
................
x-xss-protection: 1; mode=block; report=http://xntutor.com/i/xss_report

Python列出目录

原文：https://www.yiibai.com/python_network_programming/python_directory_listing.html

Python可用于从目录获取内容列表。可以使用程序列出运行python的同一台计算机中目录的内容。还可以登录到远程系统并列出远程目录中的内容。

1. 列出本地目录

在下面的示例中，使用listdir()方法获取当前目录的内容。要指示诸如文件或目录之类的内容类型，使用更多函数来评估内容的性质。

for  name in os.listdir('.'):
    if os.path.isfile(name): print 'file: ', name
    elif os.path.isdir(name): print 'dir: ', name
    elif os.path.islink(name): print 'link: ', name
    else: print 'unknown', name

当运行上面的程序时，我们得到以下输出 -

file: index.html
dir: mybooks
link: ulink

请注意，以上内容特定于运行python程序的系统。结果将因系统及其内容而异。

2. 列出远程目录

可以使用ftp访问远程系统来列出远程目录的内容。建立连接后，可以使用将以类似于本地目录列表的方式列出目录内容的命令。

from ftplib import FTP
def main():
    ftp = FTP('ftp.ibiblio.org')
    ftp.login()
    ftp.cwd('pub/yiibai/biology/') # change to some other subject
    entries = ftp.nlst()
    ftp.quit()

    print(len(entries), "entries:")
    for entry in sorted(entries):
        print(entry)

if __name__ == '__main__':
    main()

当运行上面的程序时，得到以下输出-

(6, 'entries:')
INDEX
README
acedb
dna-mutations
ecology+evolution
molbio

Python远程过程调用

原文：https://www.yiibai.com/python_network_programming/python-remote-procedure-call.html

远程过程调用(RPC)系统使我们可以使用在本地库中调用函数时所使用的语法来调用远程服务器上可用的函数。这在两种情况下很有用：

使用rpc利用多台计算机的处理能力，而无需更改用于调用远程系统中程序的代码。

处理所需的数据仅在远程系统中可用。

因此，在python中，可以将一台计算机视为服务器，将另一台计算机视为客户端，这将对服务器进行调用以运行远程过程。在下面示例中，我们将使用localhost并将其用作服务器和客户端。

1. 运行服务器

内置服务器附带python语言，可以将其作为本地服务器运行。运行该服务器的脚本位于python安装的bin文件夹下，脚本名为classic.py。可以在python提示符下运行它，并检查它是否在本地服务器上运行。

$ python bin/classic.py

当运行上面的程序时，得到以下输出-

INFO:SLAVE/18812:server started on [127.0.0.1]:18812

2. 运行客户端

接下来，使用rpyc模块运行客户端以执行远程过程调用。下面的示例中，在远程服务器中执行打印功能。

import rpyc
conn = rpyc.classic.connect("localhost")
conn.execute("print('Hello from yiibai')")

当运行上面的程序时，得到以下输出-

Hello from yiibai

4. 通过RPC进行表达评估

使用上面的代码示例，可以使用python的内置函数通过rpc执行和评估表达式。

import rpyc
conn = rpyc.classic.connect("localhost")
conn.execute('import math')
conn.eval('2*math.pi')

当运行上面的程序时，得到以下输出-

6.283185307179586