网络
将具有独立功能的多台计算机通过通信线路和通信设备连接起来,在网络管理软件及网络通信协议下,实现资源共享和信息传递的虚拟平台
网络编程
网络编程也叫做套接字编程,Socket编程,即:通信两端都独有自己的Socket对象,数据在Socket之间通过 文件流 或 数据报包的形式传输
网络编程三要素
IP地址
这是网络环境下每一台计算机的唯一标识,通过IP地址来找到指定的计算机。(标识网络中设备的一个地址)
IP地址分类
-
IPV4,采用4字节,十进制形式组成
IPV4划分: 例如: 192.168.192.130 城域网:第1段是网关地址,后3段时 主机地址,即:1+3,例如:10.?.?.? 广域网(校园网):2+2 局域网:3+1 例如:192.168.192.?
-
IPV6,采用16字节,十六进制组成
IP地址的作用:
通过IP地址找到网络中唯一一台设备,也就是说通过IP地址能够找到网络中某台设备,如何跟这个设备进行数据通信。
查看IP地址与检查网络的方法:
查看IP地址
Linux和macOS使用 ifconfig 这个命令
Windows使用 ipconfig 这个命令
检查网络是否正常使用 ping 命令
ping www.baidu.com 检查是否能上公网
ping 当前局域网的ip地址,检查是否在同一个局域网内
ping 127.0.0.1 检查本地网卡是否正常
端口
用于标识进程的逻辑地址,通过端口来找到指定的进程
端口是传输数据的通道,是数据传输必经之路
每一个端口都会有一个对应的端口号,想要找到端口通过端口号即可
端口号是:程序在设备上的唯一标识
端口号可以标识电脑中唯一的一个端口
分类
- 知名端口号:是指众所周知的端口号,范围是从0到1023
- 动态端口号:一般程序员开发应用程序使用端口号称为动态端口号,范围是从1024到65535
如何查看端口号
windos系统: netstat -ano
mac系统,linux: netstat -anp
协议
定义通信规则,符合协议则可以通信,否则无法正常通信
分类
TCP协议:类似于:打电话
1.面向有连接。
2.采用IO流(Input/Output)的方式传输数据;理论上来讲,数据无大小限制。
3.安全可靠协议。
4.效率相对较低的。
5.区分客户端和服务端。
UDP协议:类似于:群聊
1.面向无连接。
2.采用数据报包。
3.不安全、不可靠协议。
4.效率相对较高。
5.不区分客户端和服务端,叫:发送端 和 接收端。
TCP协议
数据在发送之前,需要规则,以保证程序之间按照指定的规则来进行数据的通信,这个规则就是TCP协议。
TCP的英文全拼(Transmission Control Protocol)简称传输控制协议,它是一种面向连接的、可靠的、基于字节流的传输层通信协议。
TCP通信步骤
- 创建连接
-
传输数据
-
关闭连接
说明:
TCP通信模型相当于生活中的 ‘ 打电话 ’ ,在通信开始之前,一定要先建好连接,才能发送数据,通信结束要关闭连接。
TCP协议创建连接:3次握手
三次握手(Three-Way Handshake)就是指简历一个TCP连接时,需要客户端和服务端总共发送3个包以确认连接的建立。
- 第一次握手:客户端向服务端发送请求,等待服务端确认。
- 第二次握手:服务端收到请求后知道客户端请求建立连接,回复客户端以确认连接请求。
- 第三次握手:客户端收到确认后,再次发送请求确认服务端,服务端收到正确请求后,则连接建立成功,完成三次握手。
第1次握手:客户端 => 服务端 A发送请求(随机数x)
第2次握手:服务端 => 客户端 B回复消息(x+1,y),A确认y
第3次握手:客户端 => 服务端 A回复消息(y+1),B确认y
TCP协议断开连接:4次挥手
四次挥手说的是TCP断开连接的时候,需要经过4次确认。TCP连接是双向的,A连接B、B连接A都要断开。
-
第一次挥手:当主机A(可以是客户端也可以是服务端)完成数据传输后,提出停止TCP连接的请求
-
第二次挥手:主机B收到请求后对其做出响应,确认这一方向上的TCP连接将关闭
-
第三次挥手:主机B端再次提出反方向的连接关闭请求
-
第四次挥手:主机A对主机B的请求进行反应,确认这一方向上的TCP连接关闭
第1次挥手:A发送请求(随机数u) 第2次挥手:B回消息(u+1)A确认U;关闭A到B的连接 第3次挥手:B发送消息(U+1,w) 第4次挥手:A回复消息(U+1,w+1),B确认w;关闭B到A的连接
TCP的特点
面向连接
- 通信双方必须先建立好连接,才能进行数据传输,数据传输完成后,需要断开连接
可靠传输
- 都建立了连接,传输数据可靠
- 必须要先建立连接,相对效率较低
- 大多数服务器程序都是使用TCP协议开发的,比如文件下载,网页浏览等
Socket套接字
概念
socket(简称:套接字)是进程之间通信的一个工具,好比现实生活中的插座,所有的家用电器要想工作都是基于插座进行,而进程之间想要进行网络通信需要基于socket
它是套接字的意思, 也是网络编程的核心对象.
即: 通信两端都独有自己的Socket对象, 数据在两个Socket之间通过 字节流(TCP协议) 或者 数据报包(UDP协议)的形式进行传输.
使用场景
socket负责进程之间的网络数据传输,好比数据的搬运工。
只要跟网络相关的应用程序或者软件都使用到了socket
Socket通信图解
使用
socket(套接字)能实现不同主机之间的进程间通信。Python中有专门的socket类:
# 导入socket模块
inport socket
要使用socke,则通常要使用到socket模块下的socket类创建socket对象:
函数名 | 含义 |
---|---|
socket(AddressFamily,Type) | 用于创建一个socket对象。其中,参数AddressFamily可以选择AF_INET用于Internet进程间通信,实际工作中常用它;参数Type表示套接字类型,可以是SOCK_STREAM流式套接字,主要用于TCP协议 |
Socket对象创建步骤:
1.导包
2.创建Socket对象
3.关闭,释放资源
# 1.导包
inport socket
# 2.创建socket对象
# 参数1:Address Family,地址族,即:表示用何种IP规则来解析,例如IPV4,IPV6,... AF_INET 代表 IPV4
# 参数2:表示传输方式,Stream(流的意思),表示用:字节流(二进制形式)传输数据
cli_socket = socket.socket(socket.AF_INET,socket.STREAM) # client(客户端)
# 3.打印 socket对象,看是否创建成功
print(cli_socket)
# 4.释放资源
cli_socket.close()
TCP程序开发流程
TCP网络应用程序开发分为:
- TCP客户端程序开发(ps:浏览器)
- TCP服务端程序开发
说明:
客户端程序是指运行在用户设备上的程序
服务端程序是指运行在服务器设备上的程序,专门为客户端提供数据服务。
TCP服务器端操作步骤流程:
1.创建服务端套接字对象
2.绑定端口号
3.设置监听
4.等待接收客户端的连接请求
5.发送数据
6.接收数据
7.关闭套接字
服务器端的函数
函数名 | 含义 |
---|---|
bind(addresss) | 绑定地址(host,port)到socket套接字,在AF_INET下,address以元组(host,port)的形式表示地址。其中,参数host表示字符串类型的主机名或IP地址;port表示int类型的端口号。 |
listen(backlog) | 开始TCP监听。参数backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5即可,最大值可以设置为128 |
accept() | 被动接受TCP客户端连接,等待连接的到来,返回一个connection对象,以元组形式显示,且元组的第一个参数为已建立连接的socket对象,第二个参数为地址address。 |
能同时应用于服务器端和客户端的函数
函数名 | 含义 |
---|---|
recv(bufsize) | 用于接收TCP数据,数据以bytes二进制形式返回,bufsize指定要接收的最大数据量,可设置为1024。 |
send(data) | 发送TCP数据,将data中的数据发送到连接的套接字,打他为bytes二进制数据 |
close() | 关闭套接字 |
setsockopt(level,optname,value) | 可设置端口号复用,让程序退出端口号并立即释放。level可指定为SQL_SOCKET,optname可指定为SO_REUSEADDR,value可指定为True。 |
字符串str与二进制bytes类型转换
在网络中,数据是以二进制数据类型bytes的形式进行传递的,所以在我们向网络传输数据的时候需要把数据转化成二进制
,从网络中接受的数据默认也是二进制
类型的数据,想要正常使用这些数据,也需要把这些数据从二进制
类型数据转化为字符串str
型
当字符串str数据转化为二进制bytes类型时,可使用如下函数:
encode(encoding)
用于把字符串编码转换为二进制数据,其中,encoding表示编码格式,常设置为utf-8,
当二进制bytes数据转换为字符串str类型时,可使用如下函数:
decode(encoding)
用于把二进制数据解码转换为字符串,其中,encoding表示编码格式,常设置为utf-8。
格式:
字符串.encode(encoding = ‘码表名’) # 编码 字符串 => 二进制形式, 一般用:utf-8码表
二进制字符串.decode(encoding = ‘码表名’) # 解码,二进制字符串 => 字符串,一般用utf-8码表
细节:
1.编码与解码时,码表要一致,否则可能出现:乱码的情况
2.数字,英文字母,特殊符号,无论在什么码表中,都占1个字节
中文在GBK码表(国内常用)中,占2个字节,在utf-8(万国表,统一码)码表中 占 3个字节
3.b’内容’ 这种写法 是 二进制形式的字符串,只针对于:字母,数字,特殊符号有效,针对于中文无效。即:b’abc123@#'可以,b’你好’不行
案例
'''
案例:演示TCP入门,即:服务器端给客户端发送1句话,客户端收到后,给出回执信息
流程:
1.服务器端 => 客户端发送,’Welcome to study socket!‘
2.客户端接收到消息后,打印,并给出回执信息,’消息已收到,So Easy!‘
3。服务器端收到 客户端的 回执信息,打印即可
服务器端,实现步骤:
1.创建服务器端的Socket对象
2.绑定IP地址和端口号
3.设置最大监听数(允许挂载,挂起的数量)
4.具体的监听动作,接收客户的需求,并获取1个socket对象,负责和该客户端的交互
5.给 客户端 发送1句话,二进制形式
6.接收客户端发过来的回执信息(二进制信息),记得转成 字符串 ,并打印
7.释放资源,关闭accept_socket
'''
# 当前代码为:服务器端的代码
import socket
# 1.创建服务器端的Socket对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2.绑定IP地址和端口号
server_socket.bind(('127.0.0.1',12306)) # 127.0.0.1代表本地回路(回环)地址,代表本机
# 3.设置最大监听数(允许挂载,挂起的数量)
server_socket.listen(5)
# 4.具体的监听动作,接收客户的需求,并获取1个socket对象,负责和该客户端的交互
# accept_socket:负责和客户端交互的socket对象
# client_info:客户端的IP信息
accept_socket,client_info = server_socket.accept()
# 5.给 客户端 发送1句话,二进制形式
accept_socket.send(b'Welcome to study socket!')
# 6.接收客户端发过来的回执信息(二进制信息),记得转成 字符串 ,并打印
# 1024代表一次性接收客户端数据的长度(长度:字节),超出则无法接收
recv_data_bytes = accept_socket.recv(1024)
recv_data = recv_data_bytes.decode(encoding='utf-8')
print(f'服务器端收到回执信息:{recv_data}')
# 7.释放资源,关闭accept_socket
accept_socket.close() # 和客户端交互的socket,一般要关闭
# server_socket.close() 服务器端一般不关闭
'''
案例:演示TCP入门,即:服务器端给客户端发送1句话,客户端收到后,给出回执信息
流程:
1.服务器端 => 客户端发送,’Welcome to study socket!‘
2.客户端接收到消息后,打印,并给出回执信息,’消息已收到,So Easy!‘
3。服务器端收到 客户端的 回执信息,打印即可
客户端,实现步骤:
1.创建客户端的Socket对象
2.连接服务器端的 IP地址和端口号
3.接收服务器端发过来的信息(二进制信息),记得转成 字符串 ,并打印
4.给 服务器端 发送1句话,二进制形式
5.释放资源,关闭accept_socket
'''
# 导包
import socket
# 1.创建客户端的Socket对象
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2.连接服务器端的 IP地址和端口号
client_socket.connect(('127.0.0.1',12306))
# 3.接收服务器端发过来的信息(二进制信息),记得转成字符串 ,并打印
recv_data_bytes = client_socket.recv(1024)
recv_data = recv_data_bytes.decode(encoding='utf-8')
print(f"客户端收到:{recv_data}")
# 4.给服务器端发送1句话,二进制形式
client_socket.send("消息已收到,有内鬼,终止交易,Over!".encode(encoding='utf-8'))
# 5.释放资源,关闭accept_socket
client_socket.close()
端口号重用
'''
案例:演示TCP入门,即:服务器端给客户端发送1句话,客户端收到后,给出回执信息
流程:
1.服务器端 => 客户端发送,’Welcome to study socket!‘
2.客户端接收到消息后,打印,并给出回执信息,’消息已收到,So Easy!‘
3。服务器端收到 客户端的 回执信息,打印即可
服务器端,实现步骤:
1.创建服务器端的Socket对象
2.绑定IP地址和端口号
3.设置最大监听数(允许挂载,挂起的数量)
4.具体的监听动作,接收客户的需求,并获取1个socket对象,负责和该客户端的交互
5.给 客户端 发送1句话,二进制形式
6.接收客户端发过来的回执信息(二进制信息),记得转成 字符串 ,并打印
7.释放资源,关闭accept_socket
设置端口号复用:
原因:
当服务器端关闭的时候,端口号不会立即释放,而是需要等待1~2分钟才会释放
如何解决这个问题? 即:端口号重用
'''
# 当前代码为:服务器端的代码
import socket
# 1.创建服务器端的Socket对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2.绑定IP地址和端口号
server_socket.bind(('127.0.0.1',12306)) # 127.0.0.1代表本地回路(回环)地址,代表本机
# 3.设置最大监听数(允许挂载,挂起的数量)
server_socket.listen(5)
# 4.具体的监听动作,接收客户的需求,并获取1个socket对象,负责和该客户端的交互
# accept_socket:负责和客户端交互的socket对象
# client_info:客户端的IP信息
accept_socket,client_info = server_socket.accept()
# 5.给 客户端 发送1句话,二进制形式
accept_socket.send(b'Welcome to study socket!')
# 6.接收客户端发过来的回执信息(二进制信息),记得转成 字符串 ,并打印
# 1024代表一次性接收客户端数据的长度(长度:字节),超出则无法接收
recv_data_bytes = accept_socket.recv(1024)
recv_data = recv_data_bytes.decode(encoding='utf-8')
print(f'服务器端收到回执信息:{recv_data}')
# 7.释放资源,关闭accept_socket
accept_socket.close() # 和客户端交互的socket,一般要关闭
# server_socket.close() 服务器端一般不关闭
# 8.设置端口号重用
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 参数1:代表当前的Socket对象,即:Server_socket(服务器端的Socket对象)
# 参数2:Reuse Address,表示:端口号重用,这里是:属性名
# 参数3:True,表示:成立;False,表示:不成立,这里是:属性值
多客户端形式
'''
案例:演示TCP入门,即:服务器端给客户端发送1句话,客户端收到后,给出回执信息
流程:
1.服务器端 => 客户端发送,’Welcome to study socket!‘
2.客户端接收到消息后,打印,并给出回执信息,’消息已收到,So Easy!‘
3。服务器端收到 客户端的 回执信息,打印即可
服务器端,实现步骤:
1.创建服务器端的Socket对象
2.绑定IP地址和端口号
3.设置最大监听数(允许挂载,挂起的数量)
4.具体的监听动作,接收客户的需求,并获取1个socket对象,负责和该客户端的交互
5.给 客户端 发送1句话,二进制形式
6.接收客户端发过来的回执信息(二进制信息),记得转成 字符串 ,并打印
7.释放资源,关闭accept_socket
设置端口号复用:
原因:
当服务器端关闭的时候,端口号不会立即释放,而是需要等待1~2分钟才会释放
如何解决这个问题? 即:端口号重用
'''
# 当前代码为:服务器端的代码
import socket
# 1.创建服务器端的Socket对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2.绑定IP地址和端口号
server_socket.bind(('127.0.0.1',12306)) # 127.0.0.1代表本地回路(回环)地址,代表本机
# 3.设置最大监听数(允许挂载,挂起的数量)
server_socket.listen(5)
# 如下是和客户端交互的代码,用while True包裹即可
while True:
# 4.具体的监听动作,接收客户的需求,并获取1个socket对象,负责和该客户端的交互
# accept_socket:负责和客户端交互的socket对象
# client_info:客户端的IP信息
accept_socket,client_info = server_socket.accept()
# 5.给 客户端 发送1句话,二进制形式
accept_socket.send(b'Welcome to study socket!')
# 6.接收客户端发过来的回执信息(二进制信息),记得转成 字符串 ,并打印
# 1024代表一次性接收客户端数据的长度(长度:字节),超出则无法接收
recv_data_bytes = accept_socket.recv(1024)
recv_data = recv_data_bytes.decode(encoding='utf-8')
print(f'服务器端收到回执信息:{recv_data}')
# 7.释放资源,关闭accept_socket
accept_socket.close() # 和客户端交互的socket,一般要关闭
# server_socket.close() 服务器端一般不关闭
# 8.设置端口号重用
#server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 参数1:代表当前的Socket对象,即:Server_socket(服务器端的Socket对象)
# 参数2:Reuse Address,表示:端口号重用,这里是:属性名
# 参数3:True,表示:成立;False,表示:不成立,这里是:属性值
TCP网络程序的注意点
1.TCP服务端程序必须绑定端口号,否则客户端找不到这个TCP服务端程序,为了更稳定,建议把IP也绑定
2.accept()前的套接字是被动套接字,只负责接收新的客户端的连接请求,不能收发消息
3.当TCP客户端程序和TCP服务端程序连接成功后,TCP服务器端程序会产生一个新的套接字,用于收发客户端消息
4.若关闭accept()返回的被动套接字,则表示和这个客户端已经通信完毕
5.对于服务器端socket,关闭时需慎重
6.当客户端的套接字调用close后,服务器端的recv会解阻塞,返回的数据长度为0,用于判断客户端是否已经下线
长连接 和 短连接
短连接:客户端和服务器交互一次, 如何socket对象销毁
长连接:客户端 和 服务器端可以多次交互,可以手动选择在合适的时机,关闭(释放资源) ,一般适用于:数据库的连接
案例
# 演示:长连接,即:客户端不断地给服务器端发送消息,服务器端接收消息并打印。 客户端发送886结束发送
服务器端
'''
案例:演示TCP入门,即:服务器端给客户端发送1句话,客户端收到后,给出回执信息
流程:
1.服务器端 => 客户端发送,’Welcome to study socket!‘
2.客户端接收到消息后,打印,并给出回执信息,’消息已收到,So Easy!‘
3。服务器端收到 客户端的 回执信息,打印即可
服务器端,实现步骤:
1.创建服务器端的Socket对象
2.绑定IP地址和端口号
3.设置最大监听数(允许挂载,挂起的数量)
4.具体的监听动作,接收客户的需求,并获取1个socket对象,负责和该客户端的交互
5.给 客户端 发送1句话,二进制形式
6.接收客户端发过来的回执信息(二进制信息),记得转成 字符串 ,并打印
7.释放资源,关闭accept_socket
设置端口号复用:
原因:
当服务器端关闭的时候,端口号不会立即释放,而是需要等待1~2分钟才会释放
如何解决这个问题? 即:端口号重用
'''
# 当前代码为:服务器端的代码
import socket
# 1.创建服务器端的Socket对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2.绑定IP地址和端口号
server_socket.bind(('127.0.0.1',10086)) # 127.0.0.1代表本地回路(回环)地址,代表本机
# 3.设置最大监听数(允许挂载,挂起的数量)
server_socket.listen(5)
# 4.具体的监听动作,接收客户的需求,并获取1个socket对象,负责和该客户端的交互
# accept_socket:负责和客户端交互的socket对象
# client_info:客户端的IP信息
accept_socket,client_info = server_socket.accept()
while True:
# 接收客户端发过来的回执信息(二进制信息),记得转成 字符串 ,并打印
# 1024代表一次性接收客户端数据的长度(长度:字节),超出则无法接收
recv_data_bytes = accept_socket.recv(1024)
recv_data = recv_data_bytes.decode(encoding='utf-8')
print(f'服务器端收到回执信息:{recv_data}')
# 6.如果接收到地消息是886,就结束程序
if recv_data == "886":
break
# 释放资源,关闭accept_socket.
accept_socket.close() # 和客户端交互的socket,一般要关闭
# server_socket.close() 服务器端一般不关闭
客户端
'''
案例:演示TCP入门,即:服务器端给客户端发送1句话,客户端收到后,给出回执信息
流程:
1.服务器端 => 客户端发送,’Welcome to study socket!‘
2.客户端接收到消息后,打印,并给出回执信息,’消息已收到,So Easy!‘
3。服务器端收到 客户端的 回执信息,打印即可
客户端,实现步骤:
1.创建客户端的Socket对象
2.连接服务器端的 IP地址和端口号
3.接收服务器端发过来的信息(二进制信息),记得转成 字符串 ,并打印
4.给 服务器端 发送1句话,二进制形式
5.释放资源,关闭accept_socket
'''
# 导包
import socket
# 1.创建客户端的Socket对象
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2.连接服务器端的 IP地址和端口号
client_socket.connect(('127.0.0.1',10086))
# 3.接收服务器端发过来的信息(二进制信息),记得转成字符串 ,并打印
while True:
# 3.1 提示用户录入要发送给服务器端的内容
data = input('请录入要发给服务器端的内容:')
# 3.2发送数据给 服务器端
client_socket.send(data.encode(encoding='utf-8'))
# 3.3判断是否是886,如果是,就结束发送.
if data == '886':
break
# 5.释放资源,关闭accept_socket
client_socket.close()
文件上传
服务器端
'''
案例:文件上传,即:客户端给服务器端上传1个文件
流程:
1.客户端 => 服务器端,上传1个文件
2.服务器端收到后,保存到 服务器上的某个路径下。 例如:./data/这里
服务器端,实现步骤:
1.创建服务器端的Socket对象
2.绑定IP地址和端口号
3.通过open()函数,关联:目的地文件的路径
4.(循环)接收客户端写过来的数据,并将其写到 目的地文件中
5.如果接收完毕,就结束即可。即:break
6.关闭客户端即可
'''
# 当前代码为:服务器端的代码
import socket
# 1.创建服务器端的Socket对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2.绑定IP地址和端口号
server_socket.bind(('127.0.0.1',10086)) # 127.0.0.1代表本地回路(回环)地址,代表本机
# 3.设置最大监听数(允许挂载,挂起的数量)
server_socket.listen(5)
# 4.具体的监听动作,接收客户的需求,并获取1个socket对象,负责和该客户端的交互
# accept_socket:负责和客户端交互的socket对象
# client_info:客户端的IP信息
accept_socket,client_info = server_socket.accept()
# 5.通过open()函数,关联:目的地文件的路径
with open('./data/hg.txt','wb') as dest_f:
# 6.(循环)接收客户端写过来的数据,并将其写到目的地文件中
while True:
data = accept_socket.recv(1024)
# 7.如果接收完毕,就结束即可。即:break
if len(data) <= 0:
break # 走到这里,文件读完了
# 走这里,说明读取到内容了
dest_f.write(data)
# 8..释放资源,关闭accept_socket.
accept_socket.close() # 和客户端交互的socket,一般要关闭
# server_socket.close() 服务器端一般不关闭
客户端
'''
案例:文件上传,即:客户端给服务器端上传1个文件
流程:
1.客户端 => 服务器端,上传1个文件
2.服务器端收到后,保存到 服务器上的某个路径下。 例如:./data/这里
客户端,实现步骤:
1.创建客户端的Socket对象
2.连接服务器端的 IP地址和端口号
3.通过open()函数,关联:数据源文件的路径
4.(循环)读取文件中的内容,并将其写给服务器端
5.如果读取完毕,就结束读取。即:break
6.关闭客户端即可
'''
# 导包
import socket
# 1.创建客户端的Socket对象
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2.连接服务器端的 IP地址和端口号
client_socket.connect(('127.0.0.1',10086))
# 3.通过open()函数,关联:数据源文件的路径
with open(r'd:\绕口令.txt','rb') as src_r:
# 4.(循环)读取文件中的内容,并将其写给服务器端
while True:
data = src_r.read(1024)
# 5.如果读取完毕,就结束读取。即:break
if len(data) <= 0:
break # 走这里,文件读完了
# 走这里,说明有数据,将其写给服务器端
client_socket.send(data)
# 6.释放资源,关闭accept_socket
client_socket.close()
多客户端文件上传
服务器端
'''
案例:文件上传,即:客户端给服务器端上传1个文件
流程:
1.客户端 => 服务器端,上传1个文件
2.服务器端收到后,保存到 服务器上的某个路径下。 例如:./data/这里
服务器端,实现步骤:
1.创建服务器端的Socket对象
2.绑定IP地址和端口号
3.通过open()函数,关联:目的地文件的路径
4.(循环)接收客户端写过来的数据,并将其写到 目的地文件中
5.如果接收完毕,就结束即可。即:break
6.关闭客户端即可
'''
# 当前代码为:服务器端的代码
import socket
# 1.创建服务器端的Socket对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2.绑定IP地址和端口号
server_socket.bind(('127.0.0.1',10086)) # 127.0.0.1代表本地回路(回环)地址,代表本机
# 3.设置最大监听数(允许挂载,挂起的数量)
server_socket.listen(5)
count = 0
while True:
try:
count += 1
# 4.具体的监听动作,接收客户的需求,并获取1个socket对象,负责和该客户端的交互
# accept_socket:负责和客户端交互的socket对象
# client_info:客户端的IP信息
accept_socket,client_info = server_socket.accept()
# 5.通过open()函数,关联:目的地文件的路径
file_name = './data/图片_' + str(count) + '.jpg'
with open(file_name,'wb') as dest_f:
# 6.(循环)接收客户端写过来的数据,并将其写到目的地文件中
while True:
data = accept_socket.recv(1024)
# 7.如果接收完毕,就结束即可。即:break
if len(data) <= 0:
break # 走到这里,文件读完了
# 走这里,说明读取到内容了
dest_f.write(data)
# 8..释放资源,关闭accept_socket.
accept_socket.close() # 和客户端交互的socket,一般要关闭
# server_socket.close() 服务器端一般不关闭
except:
pass