注:此博客为《python疯狂讲义》的学习笔记
端口是一个 16 位的整数,用于表示将数据交给哪个通信程序处理。 因此,端口就是应用程序 与外界交流的出入口,它是一种抽象的软件结构,包括一些数据结构和 I/O (输入/输出) 缓冲区。 不同的应用程序处理不同端 口上的数据,在同一台机器中不能有两个程序使用同一个端口 。 端 口号可以为 0~65535 ,通常将端口分为如下三类。
公认端口( Well Known Port) :喘口号为 0~1023 , 它们紧密地绑定(Binding) 一些特定 的服务。
注册端口(Registered Port):端口号为 1024~49151 ,它们松散地结II定一些服务。应用程序 通常应该使用这个范围内的端口 。
动态和/或私有端口( Dynamic and/or Private Port) : 端口号为 49152~65535,这些端口是 应用程序使用的动态端口,应用程序一般不会主动使用这些端口 。
其中 ICMP ( Internet Control Message Protocol 〕、 IGMP Cinternet Group Manage Protocol)、 ARP (Address Resolution Protocol )、 RARP C Reverse Address Resolution Protocol) 等协议都可认为是 IP 协议族的子协议。
传输层协议主要是 TCP 和 UDP, Python 提供了 socket 等模块针对传输层协议进行编程。
URL 可以由协议名 、主机、端口和资源路径组成,即满足以下格式:
protocol ://host :port/path/…/[?query-string][#anchor]
# query-string:参数,发送给http服务器的数据
# anchor:锚(跳转到网页的指定锚点位置)
例如如下的 URL 地址:
http://www.crazyit.org/index.php
urllib 模块则包含了多个用于处理 URL 的子模块。 );
通过使用 urllib 模块可以打开任意 URL 所指向的资源,就像打开本地文件一样,这样程序就 能完整地下载远程页面。如果再与第 10 章介绍的 re 模块结合使用,那么程序完全可以提取页面中 各种信息,这就是所谓的“网络爬虫”的初步原理。
在Python2.x中,urllib分为urllib和urllib2两个模块,前者用于简单下载,后者可用于http验证,cookie管理
属性名 | 元组索引 | 返回值 | 属性名 | 元组索引 | 返回值 |
---|---|---|---|---|---|
scheme | 0 | – | fragment | 5 | |
netloc | 1 | 主机和端口 | username | None | |
path | 2 | – | password | None | |
params | 3 | 资源路径附加参数 | hostname | None | |
query | 4 | 查询字符串 | port | None |
result = urlparse('http://www.crazyit.org:80/index.php;yeeku?name=fkit#frag')
print(result)
# 通过属性名和索引来获取URL的各部分
print('资源路径:', result.path, result[2])
print('参数:', result.params, result[3])
print('查询字符串:', result.query, result[4])
print('fragment:', result.fragment, result[5])
print(result.geturl())
# 输出
资源路径: /index.php /index.php
参数: yeeku yeeku
查询字符串: name=fkit name=fkit
fragment: frag frag
http://www.crazyit.org:80/index.php;yeeku?name=fkit#frag
# 解析查询字符串,返回dict
result = parse_qs('name=fkit&name=%E7%96%AF%E7%8B%82java&age=12')
print(result)
# 解析查询字符串,返回list
result = parse_qsl('name=fkit&name=%E7%96%AF%E7%8B%82java&age=12')
print(result)
# 将列表格式的请求参数恢复成请求参数字符串
print(urlencode(result))
# 输出
{'name': ['fkit', '疯狂java'], 'age': ['12']}
[('name', 'fkit'), ('name', '疯狂java'), ('age', '12')]
name=fkit&name=%E7%96%AF%E7%8B%82java&age=12
# 被拼接URL不以斜线开头
result = urljoin('http://www.crazyit.org/users/login.html', 'help.html')
print(result) # http://www.crazyit.org/users/help.html
result = urljoin('http://www.crazyit.org/users/login.html', 'book/list.html')
print(result) # http://www.crazyit.org/users/book/list.html
# 被拼接URL以斜线(代表根路径path)开头
result = urljoin('http://www.crazyit.org/users/login.html', '/help.html')
print(result) # http://www.crazyit.org/help.html
# 被拼接URL以双斜线(代表绝对URL)开头
result = urljoin('http://www.crazyit.org/users/login.html', '//help.html')
print(result) # http://help.html
urllib.request.urlopen(url, data=None).
urllib.request.urlopen(urllib.request.Request).
params = urllib.parse.urlencode({'name': 'fkit', 'password': '123888'})
f=urlopen("http://localhost:8080/test/post.jsp", data=params)
## 等价于使用附加参数,如下
#将请求参数添加到URL的后面
url = 'http://localhost:8080/test/get.jsp?%s' % params
f = urlopen(url=url)
(1) 发送PUT请求
params = 'put请求数据'.encode('utf-8')
# 创建Request对象,设置使用PUT请求
req = Request(url='http://localhost:8080/test/put',
data=params, method='PUT')
req.add_header('Referer', 'http://www.crazyit.org/')
with urlopen(req) as f:
print(f.status)
print(f.read().decode('utf-8'))
例:
import urllib.request as ur
import http.cookiejar as hc, urllib.parse
# 以指定文件创建CookieJar对象,对象将可以把cookie保存在文件中
cookie_jar = hc.MozillaCookieJar('coockie_info.txt')
cookie_processor = ur.HTTPCookieProcessor(cookie_jar)
opener = ur.build_opener(cookie_processor)
# 定义模拟Chrome浏览器的user_agent
user_agent = r'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36' \
r' (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'
# 定义请求头
headers = {'User-Agent':user_agent, 'Connection':'keep-alive'}
#-------------下面代码发送登录的POST请求----------------
# 定义登录系统的请求参数
params = {'name':'crazyit.org', 'pass':'leegang'}
postdata = urllib.parse.urlencode(params).encode()
# 创建向登录页面发送POST请求的Request
request = ur.Request('http://localhost:8080/test/login.jsp',
data = postdata, headers = headers)
# 使用OpenerDirector发送POST请求
response = opener.open(request)
print(response.read().decode('utf-8'))
# 将cookie信息写入磁盘文件
cookie_jar.save(ignore_discard=True, ignore_expires=True) # ①
#-------------下面代码发送访问被保护资源的GET请求----------------
# 创建向"受保护页面"发送GET请求的Request
request = ur.Request('http://localhost:8080/test/secret.jsp',
headers=headers)
response = opener.open(request)
print(response.read().decode())
server.py示例
s = socket.socket()
# 将socket绑定到本机IP和端口
s.bind(('192.168.43.36', 3000))
# 服务端开始监听来自客户端的连接
s.listen()
while True:
# 每当接收到客户端socket的请求时,该方法返回对应的socket和远程地址
c, addr = s.accept()
print('连接地址:', addr)
c.send('您好,您收到了服务器的新年祝福!'.encode('utf-8'))
# 关闭连接
c.close()
client.py示例
s = socket.socket()
# 连接远程主机
s.connect(('192.168.43.36', 3000))
rec = s.recv(1024).decode('utf-8')
以上a.accept()才用阻塞的方式接收消息。
通过 selectors 可实现监听消息。
主要用到的模块:smtplib,email.message.EmailMessage
使用 poplib 收取邮件可分为两步。
主要用到的模块:poplib,email.parser,email.policy
详细参考
名称 | 说明 | 值 |
---|---|---|
Accept | 告诉服务端 客户端接受什么类型的响应 | 一个或多个MIME类型 |
Cookie | – | – |
Refere | 表示这个请求是从哪个URL过来的 | url |
Cache-Control | 是否在客服端缓存 | – |
User-Agent | ||
其它 | – |
例 | 说明 |
---|---|
Cache-Control: max-age=3600 | 让客户端对响应内容缓存3600秒,也即在3600秒内,如果客户再次访问该资源,直接从客户端的缓存中返回内容给客户,不要再从服务端获取 |
ETag:“…” | 当服务端资源发生变化,这个ETag就会相应发生变化。可以让客户端“更智能”地处理什么时候要从服务端取资源,什么时候可以直接从缓存中返回响应。 |
Location: http://www.iteye.com | 其实是让客户端再发一个请求到A页面 |
Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1 | 服务端可以设置客户端的Cookie |
cmd: ipconfig/all
目的 | – |
---|---|
查看所有端口使用情况 | netstat -ano |
查看特定端口 | netstat -ano |
可以认为 UDP协议的 socket类似于码头,数据报则类似于集装箱。 码头的作用就· ‘益,是负责友送、接收集装箱, 而 socket 的作用则是发送、接收数据报。 因此, 对于基于| UDP 协议的通信双方而言,没有所谓的客户 端和服务器端的概念。