学习自刘大拿的Python课程
网络编程
- 网络编程
- 网络协议: 一套规则
- 网络模型:
- 七层模型-理论模型:任务分块,各司其职
- 物理层:如网线、水晶接头等
- 数据链路层:图像传输、电压等
- 网络层
- 传输层
- 会话层:传之前打招呼
- 表示层
- 应用层:我们现在
- 四层模型-实际应用
- 链路层:接线
- 网络
- 传输层
- 应用层
- 七层模型-理论模型:任务分块,各司其职
- 每一层都有相应的协议负责交换信息或者协同工作
- TCP/IP 协议族,说俗了,不全是
- TCP/IP 是供已连接因特网的计算机进行通信的通信协议
- TCP/IP 指传输控制协议/网际协议 (Transmission Control Protocol / Internet Protocol)。
- TCP/IP 定义了电子设备(比如计算机)如何连入因特网,以及数据如何在它们之间传输的标准。
- IP地址:负责在网络上唯一定位一个机器
- IP地址分ABCDE类
- 是由四个数字段组成,每个数字段的取值是0-255(数量肯定不够,以一层套一层的分级方式增加数量),所以有局域网、广域网
- 192.168.xxx.xxx:表示局域网ip
- 127.0.0.1:表示本机
- IPv4(不太够用,所以有IPv6),
IPv6(中国刚开始用)
- 端口(机器中所有的软件都有一个端口号,为该软件的编码)
e.x.发QQ,IP用来锁定机器,端口用来锁定软件- 范围: 0-65535
- 知名端口:0-1023 安排了位置
- 非知名端口:1024- 未被占用即可用
常见知名端口 端口号 HTTP 80 FTP 21 SSH 22 MSG ICP 29 MySQL 3306
自己做,端口号往大了做,一万起
- 范围: 0-65535
TCP/UDP协议
两者是挂号信与凭信的区别,前者类似当今快递,靠编号邮寄接受;后者类似送信,靠邮寄地址接收
- UDP:非安全的不面向链接的传输
- 安全性差
- 大小限制64kb:超过的话就切断,无序
- 没有顺序
- 速度快
- TCP
- 基于链接的通信(传信之前建立虚拟通路,对方已知有信)
- Socket编程:解决如何和对方通信,包括找着对方(IP+端口);发消息(UDP/TCP)
- socket(套接字): 是一个网络通信的端点, 能实现不同主机的进程通信,网络大多基于Socket通信
- 通过IP+端口定位对方并发送消息的通信机制
- 分为UDP和TCP
即时通讯一般用UDP
通信有两端 - 客户端Client: 发起访问的一方
① 建立程序 socket
② 发送消息(知道IP + port的绑定信息)
③ 等待反馈 - 服务器端Server:接受访问的一方
想要通信,服务端需要:
① 建立socket (用socket通信)
② port (提供连接外面的端口) + IP等信息 (绑定)
③ 接受访问
④ 反馈(不必须)
UDP 编程
- Server端流程
- 1. 建立socket,socket是负责具体通信的一个实例
- 2. 绑定,为创建的socket指派固定的端口和ip地址
- 3. 接受对方发送内容
- 4. 给对方发送反馈,此步骤为非必须步骤
- Client端流程
- 1. 建立通信的socket
- 2. 发送内容到指定服务器
- 3. 接受服务器给定的反馈内容
- 服务器 案例01
'''
Server端流程
1.建立socket,socket是负责具体通信的一个实例
2.绑定,为创建的socket指派固定的端口和ip地址
3.接受对方发送内容
4.给对方发送反馈,此步骤为非必须步骤
'''
# socket模块负责socket编程
import socket
# 模拟服务器的函数
def serverFunc():
# 建立socket
# socket.AF_INET:使用ipv4协议
# socket.SOCK_DGRAM: 选择通信方式,使用UDP通信
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 设置和绑定IP和port
# 127.0.0.1: 这个IP地址代表的是机器本身
# 7852: 随便的端口
# 地址是一个tuple类型,(IP,port)
addr = ("127.0.0.1", 7852 )
sock.bind(addr)
# 接收对方消息
# 等待方式:死等,没有其他可能性
# recvfrom接收的返回值是一个元祖(tuple),前一项表示数据,后一项表示地址
# 参数的含义是缓冲区大小
# rst = sock.recvfrom(500) 可以这么写
data, addr = sock.recvfrom(500)
# 直接将接收到的两个值 数据(这里是消息)和元祖(port + IP)赋值给两个参数
# 发过来的数据是一个字节流(bytes流),需要解码
print(data)
print(type(data))
# 将发送过来的字节流解码得到str格式内容
# decode默认参数是utf8
# text = data.decode()
text = data.decode()
print(type(text))
print(text)
# 给对方返回消息
rsp = "Ich hab keine Hunge.(德语)"
# 发送的数据需要编码成bytes格式
# 默认是utf8
data = rsp.encode()
sock.sendto(data, addr)
if __name__ == '__main__':
print("Starting server.......")
serverFunc()
print("Ending server........")
- 客户端 案例02
'''
Client端流程
1. 建立通信的socket
2. 发送内容到指定服务器
3. 接受服务器给定的反馈内容
'''
import socket
def clientFunc():
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
text = "Do you want to have a date with me? "
# 发送的必须是bytes格式
data = text.encode()
# 发送
sock.sendto(data, ("127.0.0.1", 7852))
# 等待对方给出反馈
data, addr = sock.recvfrom(200)
text = data.decode()
print(text)
if __name__ == '__main__':
clientFunc()
# 顺序:先启动Server案例01.py程序
Server端运行结果
Starting server.......
b'Do you want to have a date with me? '
<class 'bytes'>
<class 'str'>
Do you want to have a date with me?
Ending server........
Client端运行结果
Ich hab keine Hunge.(德语)
有时候程序运行完了,并不意味着端口空闲,有可能还在别占用,所以想在此使用该端口会报错。
- 服务器程序要求永久运行(不能死,也不崩溃,这也是Linux系统在服务区常用的原因),一般用死循环处理
- 不死服务器版本,运行命令加入死循环 案例03
if __name__ == '__main__':
import time
while 1:
try:
serverFunc()
except Exception as e:
print(e)
time.sleep(1)
TCP编程
- 面向链接的传输,即每次传输之前需要先建立一个链接
- 客户端和服务器端两个程序需要编写
- Server端的编写流程
建立socket负责具体通信,这个socket其实只负责接受对方的请求,真正通信的是链接后从新建立的socket
绑定端口和地址
监听接入的访问socket(一定时间内查询一次)
接受访问的socket,可以理解接受访问即建立了一个通讯的链接通路(虚拟通道)
接受对方的发送内容,利用接收到的socket接收内容
如果有必要,给对方发送反馈信息
关闭链接通路(关闭虚拟通路) - Client端流程
建立通信socket
链接对方,请求跟对方建立通路
发送内容到对方服务器
接受对方的反馈
关闭链接通路 - 案例04 服务器端
import socket
def tcp_srv():
# 1. 建立socket负责具体通信,这个socket其实只负责接受对方的请求,真正通信的是链接后从新建立的socket
# 需要用到两个参数
# AF_INET: 含义同udp一致
# SOCK_STREAM: 表明是使用的tcp进行通信
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 绑定端口和地址
# 此地址信息是一个元组类型内容,元组分两部分,第一部分为字符串,代表ip,第二部分为端口,是一个整数,推荐大于10000
addr = ("127.0.0.1", 8998)
sock.bind(addr)
# 3. 监听接入的访问socket
sock.listen() # 等待时间可修改
# 服务器死循环,永远接收请求
while True:
# 4. 接收访问的socket,可以理解接受访问即建立了一个通讯的链接通路
# accept返回的元组第一个元素赋值给skt,第二个赋值给addr
skt,addr = sock.accept()
# 5. 接收对方的发送内容,利用接收到的socket接收内容
# 500代表接收使用的buffersize
#msg = skt.receive(500)
msg = skt.recv(500)
# 接收到的是bytes格式内容
# 想得到str格式的,需要进行解码
msg = msg.decode()
rst = "Received msg: {0} from {1}".format(msg, addr)
print(rst)
# 6. 如果有必要,给对方发送反馈信息
skt.send(rst.encode())
# 7. 关闭链接通路
skt.close()
# 一次接通通道,完成多次传输再关闭通道,可以节省资源
if __name__ == "__main__":
print("Starting tcp server.......")
tcp_srv()
print("Ending tcp server.......")
- 案例05 客户端
import socket
def tcp_clt():
# 1. 建立通信socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 连接对方,请求跟对方建立通路
addr = ("127.0.0.1", 8998)
sock.connect(addr)
# 3. 发送内容到对方服务器
msg = "中文我好像也能懂"
sock.send(msg.encode())
# 4. 接收对方的反馈
rst = sock.recv(500)
print(rst.decode())
# 5. 关闭连接通路
sock.close()
if __name__ == "__main__":
tcp_clt()
运行结果
# Server
Starting tcp server.......
Received msg: 中文我好像也能懂 from ('127.0.0.1', 57990)
# Client
Received msg: 中文我好像也能懂 from ('127.0.0.1', 57990)
FTP编程
- FTP(File Transfer Protocol)文件传输协议
- 用途: 定制一些特殊的上传下载文件的服务
- 用户分类: 登陆FTP服务器必须有一个账号
- Real账户: 注册账户
- Guest账户: 可能临时对某一类人的行为进行授权
- Anonymous账户: 匿名账户,允许任何人
- FTP工作流程
端口 | 方向 |
---|---|
21 | 客户端 → 服务端 |
22 | 服务端 → 客户端 |
- 客户端链接远程主机上的FTP服务器
- 客户端输入用户名和密码(或者“anonymous”和电子邮件地址)
- 客户端和服务器进行各种文件传输和信息查询操作(客户端向服务器发起的一些命令)
- 客户端从远程FTP服务器退出,结束传输
- FTP文件表示
分三段表示FTP服务器上的文件- HOST: 主机地址,类似于 ftp.mozilla.org, 以ftp开头 (mozilla.org表明是谁家的服务器)
(url的访问地址一般为www.mozilla.org
,mozilla.org
为火狐的母公司,) - DIR:目录, 表示文件所在本地的路径,例如 pub/android/focus/1.1-RC1/
- File:文件名称, 例如 Klar-1.1-RC1.apk
- HOST: 主机地址,类似于 ftp.mozilla.org, 以ftp开头 (mozilla.org表明是谁家的服务器)
如果想完整精确表示ftp上某一个文件,需要上述三部分组合在一起
- 案例06
# 需要导入相应包,主要是ftplib
import ftplib # 关于FTP的操作都在这个包里边
import os
import socket
# 三部分精确表示在ftp服务器上的某一个文件
# 好多公开ftp服务器访问会出错或者没有反应
HOST = "ftp.acc.umu.se"
DIR = 'Public/EFLIB/'
FILE = 'README'
# 1. 客户端链接远程主机上的FTP服务器
try: # 远程连接服务器有可能出现问题,所有一般要try
f = ftplib.FTP()
# 通过设置调试级别可以方便调试
f.set_debuglevel(2)
# 链接主机地址
f.connect(HOST)
except Exception as e:
print(e)
exit()
print("***Connected to host {0}".format(HOST))
# 2. 客户端输入用户名和密码(或者“anonymous”和电子邮件地址)
try:
# 登录如果没有输入用户信息,则默认使用匿名登录
f.login()
except Exception as e:
print(e)
exit()
print("***Logged in as 'anonymous'")
# 3. 客户端和服务器进行各种文件传输和信息查询操作
try:
# 更改当前目录到指定目录
f.cwd(DIR)
except Exception as e:
print(e)
exit()
print("*** Changed dir to {0}".format(DIR))
try:
# 从FTP服务器上下载文件
# 第一个参数是ftp命令
# 第二个参数是回调函数
# 此函数的意思是,执行RETR命令,下载文件到本地后,运行回调函数
f.retrbinary('RETR {0}'.format(FILE), open(FILE, 'wb').write)
except Exception as e:
print(e)
exit()
# 4. 客户端从远程FTP服务器退出,结束传输
f.quit()
网友评论