Urllib
# -*- coding: utf-8 -*-
from urllib.parse import *
import urllib
# 解析URL字符串
result = urlparse('http://www.crazyit.org:80/index.php;yeeku?name=fkit#frag')
print(result)
# 通过属性名和索引来获取URL的各部分
print('scheme:', result.scheme, result[0])
print('主机和端口:', result.netloc, result[1])
print('主机:', result.hostname)
print('端口:', result.port)
print('资源路径:', result.path, result[2])
print('参数:', result.params, result[3])
print('查询字符串:', result.query, result[4])
print('fragment:', result.fragment, result[5])
print(result.geturl())
# 恢复URL字符串
result1 = urlunparse(('http', 'www.crazyit.org:80', 'index.php', 'yeeku', 'name=fkit', 'frag')) # 元组形式
print('url为: ', result1)
result2 = parse_qs('name=fkit&name=%E7%96%AF%E7%8B%82java&age=12')
print(result2) # 返回dict
print(urlencode(result2))
result3 = parse_qsl('name=fkit&name=%E7%96%AF%E7%8B%82java&age=12') # l 代表list
print(result3) # 返回list
print(urlencode(result3))
# urljoin() 函数负责将两个URL拼接在一起,返回代表绝对地址的URL。
# 被拼接的URL只是一个相对路径path(不以斜线开头),那么该URL将会被拼凑到base之后,如果base本身包含path部分,则用拼接的部分替换base所包含的path部分。
# 被拼接的URL是一个根路径path(以单斜线开头),那么该URL将会被拼接到base的域名之后。
# 被拼接的URL是一个绝对路径(以双斜线开头),那么该URL将会被拼接到base的scheme之后
# 被拼接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
# 被解析的 URL 以双斜线(//)开头,那么 urlparse() 函数可以识别出主机,只是缺少 scheme 部分。
result = urlparse('//www.crazyit.org:80/index.php')
print('scheme:', result.scheme, result[0])
print('主机和端口:', result.netloc, result[1])
print('资源路径:', result.path, result[2])
print('-----------------')
# 被解析的 URL 既没有 scheme,也没有以双斜线(//)开头,那么 urlparse() 函数将会把这些 URL 都当成资源路径。
result = urlparse('www.crazyit.org:80/index.php')
print('scheme:', result.scheme, result[0])
print('主机和端口:', result.netloc, result[1])
print('资源路径:', result.path, result[2])
print('++++++++++++++++++')
# -*- coding: utf-8 -*-
from urllib.request import *
import urllib.parse
# with 所求值的对象必须有一个enter()方法,一个exit()方法
# with**后面的语句被求值后,返回对象的**__enter__()方法被调用 ,方法的返回值被赋值给as 后面的变量
# with后面的代码块全部执行完之后,将调用前面返回对象的exit()方法
# urlopen() 打开URL指定的资源,并从中读取数据
# 打开URL对应的资源
result = urlopen('http://www.crazyit.org/index.php')
# 按字节读取数据
data = result.read(326)
# 将字节数据恢复成字符串
print(data.decode('utf-8'))
# 用context.manager来管理打开的URL资源
with urlopen('http://www.crazyit.org/index.php') as f:
# 按字节读取数据
data = f.read(326)
# 将字节数据恢复成字符串
print(data.decode('utf-8'))
# 在使用URLopen函数时,可以通过data属性向被请求的URL发送数据。
# with urlopen(url='http://localhost:8888/test/test',
# data='测试数据'.encode('utf-8')) as f:
# # 读取服务器全部相应
# print(f.read().decode('utf-8'))
# 服务端需要进行接收相应
# 使用URLopen()函数向服务器页面发送GET请求参数,则无须使用data属性,直接把请求参数附加在URL之后即可
params = urllib.parse.urlencode({'name': 'fkit', 'password': '123888'})
# 将请求参数添加到url的后面去
url = 'http://localhost:8888/test/get.jsp?%s' % params
with urlopen(url=url) as f:
# 读取服务器全部响应
print(f.read().decode('utf-8'))
params = 'put请求数据'.encode('utf-8')
# 创建Request对象,设置使用PUT请求
req = Request(url='http://localhost:8888/test/put', data=params, method='PUT')
with urlopen(req) as f:
print(f.status)
print(f.read().decode('utf-8'))
TCP通信协议
# -*- coding: utf-8 -*-
import socket
# 服务端
'''
socket的TCP协议通信的 服务器端
'''
# 实例化创建socket对象,默认为TCP协议类型通信
s = socket.socket()
host = socket.gethostname() # 获取计算机全名
port = 1234 # 指定计算机端口号
s.bind((host, port)) # 服务器首次调用 bind方法绑定主机和端口,
s.listen(2) # 服务器端其次调用 listen方法来监听特定的地址
# 循环调用socket的 accept()方法接受来自客户端的连接
while True:
# 服务器端套接字开始监听后,就可接受客户端连接了
# accept方法将同步阻断等待到客户端连接到来为止,然后返回一个(client,address)的元组
# 返回的元组其中client是一个客户端套接字,address是前面解释过的地址
c, addr = s.accept()
print(c)
print('连接地址: ', addr)
# 注意:传输数据,套接字提供两个方法:send 和 recv,分别表示发送和接受数据
c.send('你好,服务端向你发来问候'.encode('utf-8')) # send方法发送数据,注意编码方式
c.close()
# -*- coding: utf-8 -*-
import socket
# 客户端
'''
客户端调用connect()方法连接远程服务器
'''
s = socket.socket()
host = socket.gethostname()
port = 1234
s.connect((host, port))
# 调用recv方法获取服务端发送的消息并输出
print(s.recv(1024).decode('utf-8'))
多线程进行通信
# -*- coding: utf-8 -*-
import socket
import threading
# 列表保存所有的socket
socket_list = []
ss = socket.socket()
ss.bind(('192.168.50.60', 1235)) # 绑定本机主机 和端口
ss.listen() # 开始监听来自客户端的链接
def read_from_client(s):
# 定义函数,用于尝试接收数据,如果没有接收到数据则说明此通信段关闭,从列表中删除此通信客户端。
try:
return s.recv(2048).decode('utf-8')
# 如果捕获到异常,则表明该socket对应的客户端已经关闭,删除该socket
except:
socket_list.remove(s)
def server_target(s):
# 该函数将会作为线程执行的 target,负责处理每个 socket的通信服务器端
try:
# 循环不断的从 socket 中读取 来自客户端发送来的数据
while True:
content = read_from_client(s)
print(content)
if content is None:
break
# 当服务器端线程读取到客户端数据后,程序遍历 socket_list列表,列表中的每个 socket 都发送一次
for client_s in socket_list:
client_s.send(content.encode('utf-8'))
except Exception as e:
print(e.strerror)
# 循环不断准备接收来自客户端的连接,并为每一个客户启动一个线程服务
while True:
s, addr = ss.accept() # 准备接收来自客户端的连接,此代码会阻塞,一直等待别人的连接
socket_list.append(s) # 将socket加入socket_list列表里保存,然后启动线程
print(socket_list)
# 接收到客户端连接后,就启动一个线程为该客户端服务
threading.Thread(target=server_target, args=(s, )).start()
# -*- coding: utf-8 -*-
import socket
import threading
s = socket.socket()
# 服务端所在地的 ip和端口
s.connect(('192.168.50.60', 1235))
# 读取服务端发送的数据
def read_from_server(s):
while True:
print(s.recv(2048).decode('utf-8'))
# 客户端启动读取服务端发送数据的线程
threading.Thread(target=read_from_server, args=(s, )).start()
while True:
line = input('')
if line is None or line == 'exit':
break
# 发送用户输入的内容
s.send(line.encode('utf-8'))
UDP通信协议
# -*- coding: utf-8 -*-
# type=SOCK_DGRAM 创建基于UDP协议的socket
# socket.sendto(bytes,address) 发送数据。将bytes数据发送到address地址
# socket.recvfrom(bufsize[, flags]) 接收数据。该方法可以同时返回 socket 中的数据和数据来源地址
# UDP协议进行网络通信时,双方都需要建立一个socket对象,用于接收或者发送数据报
# 通常具有固定 ip 地址和端口的socket对象所在的程序被称为服务器,socket 应该调用bind() 方法被绑定到指定 IP 地址和端口,客户端通过ip地址与端口号同服务端建立连接后,才能向其发送数据报
# UDP协议适用于一次只传输少量数据、对可靠性要求不高的应用环境
# TCP协议面向连接的通信协议,UDP面向非连接的协议,没有建立连接的过程,通信效率高,可靠性低
import socket
books = ('大主宰', '武动苍穹', '遮天', '完美世界', '斗破苍穹', '斗罗大陆')
ss = socket.socket(type=socket.SOCK_DGRAM) # 创建基于UDP通信协议的socket
ss.bind(('192.168.50.60', 123))
for i in range(100):
# socket的UDP协议通信的 recvfrom方法 接收数据,可以同时返回socket中的数据和数据来源地址
data, addr = ss.recvfrom(4096) # 4096 数据报的大小最大为4KB 4096Byte(字节)
print(data.decode('utf-8'))
send_data = books[i % 4].encode('utf-8') # 求余 定义服务器端发送的数据报内容
# socket的UDP协议通信的 sendto方法 发送数据到指定地址
ss.sendto(send_data, addr)
ss.close()
# -*- coding: utf-8 -*-
# 客户端循环不断读取用户的输入内容,通过数据报发送出去
import socket
s = socket.socket(type=socket.SOCK_DGRAM)
while True:
line = input('')
if line is None or line == 'exit':
break
data = line.encode('utf-8')
s.sendto(data, (socket.gethostname(), 123))
data1 = s.recv(4096)
print(data1.decode('utf-8'))
s.close()