Python网络编程

网络

将具有独立功能的多台计算机通过通信线路和通信设备连接起来,在网络管理软件及网络通信协议下,实现资源共享和信息传递的虚拟平台

image-20250413173004615

网络编程

网络编程也叫做套接字编程,Socket编程,即:通信两端都独有自己的Socket对象,数据在Socket之间通过 文件流 或 数据报包的形式传输

网络编程三要素

IP地址

这是网络环境下每一台计算机的唯一标识,通过IP地址来找到指定的计算机。(标识网络中设备的一个地址)image-20250413173553577

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地址能够找到网络中某台设备,如何跟这个设备进行数据通信。image-20250413174158071

查看IP地址与检查网络的方法:
查看IP地址
Linux和macOS使用 ifconfig 这个命令
Windows使用 ipconfig 这个命令
检查网络是否正常使用 ping 命令
ping www.baidu.com 检查是否能上公网
ping 当前局域网的ip地址,检查是否在同一个局域网内
ping 127.0.0.1 检查本地网卡是否正常

端口

用于标识进程的逻辑地址,通过端口来找到指定的进程

端口是传输数据的通道,是数据传输必经之路

image-20250416231442390

每一个端口都会有一个对应的端口号,想要找到端口通过端口号即可

端口号是:程序在设备上的唯一标识

端口号可以标识电脑中唯一的一个端口

image-20250416233937912

分类
  • 知名端口号:是指众所周知的端口号,范围是从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通信步骤
  • 创建连接

image-20250416235315724

  • 传输数据

  • 关闭连接

说明:

​ TCP通信模型相当于生活中的 ‘ 打电话 ’ ,在通信开始之前,一定要先建好连接,才能发送数据,通信结束要关闭连接。

TCP协议创建连接:3次握手

三次握手(Three-Way Handshake)就是指简历一个TCP连接时,需要客户端和服务端总共发送3个包以确认连接的建立。image-20250416235739197

  • 第一次握手:客户端向服务端发送请求,等待服务端确认。
  • 第二次握手:服务端收到请求后知道客户端请求建立连接,回复客户端以确认连接请求。
  • 第三次握手:客户端收到确认后,再次发送请求确认服务端,服务端收到正确请求后,则连接建立成功,完成三次握手。
第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都要断开。

image-20250417000815631

image-20250417000827223

  • 第一次挥手:当主机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协议)的形式进行传输.

image-20250417003121974

image-20250417003137961

使用场景

socket负责进程之间的网络数据传输,好比数据的搬运工。

只要跟网络相关的应用程序或者软件都使用到了socket

Socket通信图解

image-20250417154336020

使用

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服务端程序开发

说明:

​ 客户端程序是指运行在用户设备上的程序

​ 服务端程序是指运行在服务器设备上的程序,专门为客户端提供数据服务。

image-20250417160028596

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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值