目录:
01_socket.udp
01_socket的基本使用
import socket
"""
找到终端,ls一下,跳到桌面:cd Desktop/;跳到python就业班:cd python就业班/;
清空一下桌面:clear;ls一下;vim pd_01_socket的基本使用 打开查看内容,使用":q";关闭
python3 pd_01_socket的基本使用 运行.(必须严格执行上边的步骤打开)
用python2运行:python pd_01_socket的基本使用 打开;
技巧:ctrl + a 跳到行首
ctrl + e 跳到行末
"""
def main():
# 创建一个udp套接字
udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
# 可以使用套接字收发数据
# udp_socket.sendto("发送内容",("对方的IP",端口port)元组类型别忘了加括号)
udp_socket.sendto("ha ha ha",("169.254.4.219",8080))
# 由于sendto()方法要求第一个参数为bytes(字节)类型,
# 故在字符串"ha ha ha"前边加一个字母b使之变为bytes类型
# 关闭套接字
udp_socket.close()
# 导入模块后直接输入下方代码,再定义main函数进行书写代码主体
if __name__ == '__main__':
main()
# 在终端如何运行?
02_从键盘上获取数据发送
import socket
"""
# 在终端如何运行?
找到终端,ls一下,跳到桌面:cd Desktop/;跳到python就业班:cd python就业班/;
清空一下桌面:clear;ls一下;vim pd_01_socket的基本使用 打开查看内容,使用":q";关闭
python3 pd_01_socket的基本使用 运行.(必须严格执行上边的步骤打开)
用python2运行:python pd_01_socket的基本使用 打开;
技巧:ctrl + a 跳到行首
ctrl + e 跳到行末
"""
def main():
# 创建一个udp套接字
udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
# 为实现从键盘获取数据,不再只传送固定的数据
send_data = input("请输入要传送的数据:")
# 可以使用套接字收发数据
# udp_socket.sendto("发送内容",("对方的IP",端口port)元组类型别忘了加括号)
# udp_socket.sendto(b"hahaha",("169.254.4.219",8080))
# 由于内部发送内容变成了变量不在是一个字符串,无法使用在前边加一个字母b使之变为字节类型
# 因此使用send_data.encode("utf-8")进行传输
udp_socket.sendto(send_data.encode("utf-8"),("169.254.4.219",8080))
# 关闭套接字
udp_socket.close()
# 导入模块后直接输入下方代码,再定义main函数进行书写代码主体
if __name__ == '__main__':
main()
03_循环发送
import socket
"""
# 在终端如何运行?
找到终端,ls一下,跳到桌面:cd Desktop/;跳到python就业班:cd python就业班/;
清空一下桌面:clear;ls一下;vim pd_01_socket的基本使用 打开查看内容,使用":q";关闭
python3 pd_01_socket的基本使用 运行.(必须严格执行上边的步骤打开)
用python2运行:python pd_01_socket的基本使用 打开;
技巧:ctrl + a 跳到行首
ctrl + e 跳到行末
"""
# 实现循环输入
# 使用ctrl + c可以强制退出循环
def main():
# 创建一个udp套接字
udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
while True:
# 为实现从键盘获取数据,不再只传送固定的数据
send_data = input("请输入要传送的数据:")
# 可以使用套接字收发数据
# udp_socket.sendto("发送内容",("对方的IP",端口port)元组类型别忘了加括号)
# udp_socket.sendto(b"hahaha",("169.254.4.219",8080))
# 由于内部发送内容变成了变量不在是一个字符串,无法使用在前边加一个字母b使之变为字节类型
# 因此使用send_data.encode("utf-8")进行传输
udp_socket.sendto(send_data.encode("utf-8"),("169.254.4.219",8080))
# 关闭套接字
# 全部传输完成后在关闭套接字,因此不要把关闭套接字放在循环中
udp_socket.close()
# 导入模块后直接输入下方代码,再定义main函数进行书写代码主体
if __name__ == '__main__':
main()
04_带有退出功能的循环发送
import socket
"""
# 在终端如何运行?
找到终端,ls一下,跳到桌面:cd Desktop/;跳到python就业班:cd python就业班/;
清空一下桌面:clear;ls一下;vim pd_01_socket的基本使用 打开查看内容,使用":q";关闭
python3 pd_01_socket的基本使用 运行.(必须严格执行上边的步骤打开)
用python2运行:python pd_01_socket的基本使用 打开;
技巧:ctrl + a 跳到行首
ctrl + e 跳到行末
"""
# 实现循环输入
# 使用ctrl + c可以强制退出循环
def main():
# 创建一个udp套接字
udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
while True:
# 为实现从键盘获取数据,不再只传送固定的数据
send_data = input("请输入要传送的数据:")
# 若果输入exit,那么就退出程序
if send_data == "exit":
# 使用下方代码依旧是强退
# udp_socket.close()
# 使用continue?
# 使用break退出整个while循环
break
# 可以使用套接字收发数据
# udp_socket.sendto("发送内容",("对方的IP",端口port)元组类型别忘了加括号)
# udp_socket.sendto(b"hahaha",("169.254.4.219",8080))
# 由于内部发送内容变成了变量不在是一个字符串,无法使用在前边加一个字母b使之变为字节类型
# 因此使用send_data.encode("utf-8")进行传输
udp_socket.sendto(send_data.encode("utf-8"),("169.254.4.219",8080))
# encode是编码的意思,将一个字符串类型编译成utf-8/gbk(windows用的形式)的格式
# 关闭套接字
# 全部传输完成后在关闭套接字,因此不要把关闭套接字放在循环中
udp_socket.close()
# 导入模块后直接输入下方代码,再定义main函数进行书写代码主体
if __name__ == '__main__':
main()
05_绑定端口用来接收数据
import socket
def main():
# 1.创建套接字
udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
# 2.绑定一个本地信息,绑定的是一个元组类型
localaddr = ("",41786) # 此处本地的IP如果唯一,就不用写了.端口的数值要求;大于1024
udp_socket.bind(localaddr) # 绑定,绑谁?绑上方变量内部的信息
# 3.接收数据
recv_data = udp_socket.recvfrom(1024) # 1024表示本次接收的最大字节数
# recv_data这个变量中存储的是一个元组(接收到的数据,(发送方的ip,端口))
# 4.打印接收到的数据
print(recv_data)
# 5.关闭套接字
udp_socket.close()
if __name__ == "__main__":
main()
06_解析出接收的数据
import socket
def main():
# 1.创建套接字
udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
# 2.绑定一个本地信息,绑定的是一个元组类型 必须绑定自己电脑的IP以及端口,其他的不行
localaddr = ("",5566) # 此处本地的IP如果唯一,就不用写了.端口的数值要求;大于1024
udp_socket.bind(localaddr) # 绑定,绑谁?绑上方变量内部的信息
# 3.接收数据
# 实现循环接收数据
while True:
recv_data = udp_socket.recvfrom(1024) # 1024表示本次接收的最大字节数
# recv_data这个变量中存储的是一个元组(接收到的数据,(发送方的ip,端口))
recv_msg = recv_data[0] # 存储接收的数据
send_addr = recv_data[1] # 存储发送方的地址信息
# 4.打印接收到的数据
# print(recv_data)
# print("%s:%s"%(str(send_addr),recv_msg.decode("utf-8")))
print("%s:%s" % (str(send_addr), recv_msg.decode("gbk")))
# 由于要输出两个字符串类型,send_addr,recv_msg均不是字符串类型,用str()将send_addr
# 强制转换成字符串类型,而recv_msg是由发送方发送过来已经编译成utf-8形式
# (若是从windows发送过来的,则全是gbk形式,需要解码gbk),故此处要用decode进行解码
# 5.关闭套接字
udp_socket.close()
if __name__ == "__main__":
main()
07_先绑定端口再循环发送
import socket
"""
# 在终端如何运行?
找到终端,ls一下,跳到桌面:cd Desktop/;跳到python就业班:cd python就业班/;
清空一下桌面:clear;ls一下;vim pd_01_socket的基本使用 打开查看内容,使用":q";关闭
python3 pd_01_socket的基本使用 运行.(必须严格执行上边的步骤打开)
用python2运行:python pd_01_socket的基本使用 打开;
技巧:ctrl + a 跳到行首
ctrl + e 跳到行末
"""
# 实现循环输入
# 使用ctrl + c可以强制退出循环
def main():
# 创建一个udp套接字
udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
# 绑定本地信息
# 如果不绑定就会系统随机分配端口,每次调用程序都会分配不同的端口,发送方可以不绑定,接收方绑定
udp_socket.bind(("",7890))
while True:
# 为实现从键盘获取数据,不再只传送固定的数据
send_data = input("请输入要传送的数据:")
# 可以使用套接字收发数据
# udp_socket.sendto("发送内容",("对方的IP",端口port)元组类型别忘了加括号)
# udp_socket.sendto(b"hahaha",("169.254.4.219",8080))
# 由于内部发送内容变成了变量不在是一个字符串,无法使用在前边加一个字母b使之变为字节类型
# 因此使用send_data.encode("utf-8")进行传输
udp_socket.sendto(send_data.encode("utf-8"),("169.254.4.219",8080))
# 关闭套接字
# 全部传输完成后在关闭套接字,因此不要把关闭套接字放在循环中
udp_socket.close()
# 导入模块后直接输入下方代码,再定义main函数进行书写代码主体
if __name__ == '__main__':
main()
08_使用同一个套接字进行收发数据
import socket
"""同一个套接字可以收数据也可以发数据即同时收发数据x"""
def main():
# 创建一个udp套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 获取对方的IP
dest_addr = input("请输入对方的IP:")
dest_port = int(input("请输入对方的端口:"))
# 为实现从键盘获取数据,不再只传送固定的数据
send_data = input("请输入要传送的数据:")
# 可以使用套接字收发数据
# udp_socket.sendto("发送内容",("对方的IP",端口port)元组类型别忘了加括号)
# udp_socket.sendto(b"hahaha",("169.254.4.219",8080))
# 由于内部发送内容变成了变量不在是一个字符串,无法使用在前边加一个字母b使之变为字节类型
# 因此使用send_data.encode("utf-8")进行传输
udp_socket.sendto(send_data.encode("utf-8"), (dest_addr, dest_port))
# 关闭套接字
udp_socket.close()
# 导入模块后直接输入下方代码,再定义main函数进行书写代码主体
if __name__ == '__main__':
main()
09_案例:udp聊天
"""
import socket
def main():
# 创建套接字
udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
# 创建完套接字,要想成功的接收到发送过来的信息,首先要有一个固定的端口号-绑定一个端口
# 绑定本地信息
udp_socket.bind("",7788)
# while循环处理收发信息
while True:
# 发送:
# 获取要发送的内容
dest_ip = input("请输入要发送目标的ip:")
dest_port = input("请输入要发送目标的port:")
send_massage = input("请输入要发送的信息:")
udp_socket.sendto(send_massage.encode("utf-8"),(dest_ip,dest_port)) # 产生
# dest_ip,dest_port的需求,即在下方定义,定义完成后发现应该在前边进行定义,复制粘贴即可
# 接收数据并显示
recv_data = udp_socket.recvfrom(1024) # recvfrom()方法返回的是一个元组类型
print("%s:%S" % (str(recv_data[1]),recv_data[0].encode("utf-8")))
# 除了与windows进行通信以外都用utf-8进行转化,windows用gbk.[1]代表元组内部第2部分
# 注意:一个具有独立功能的代码块要封装到一个函数之中
if __name__ == '__main__':
main()
"""
# 注意:一个具有独立功能的代码块要封装到一个函数之中,以上代码做如下修改:将与发送和接收相关的
# 代码分别封装在发送,接收两个函数中
import socket
def send_data(udp_socket): # 定义成函数后,是否需要传参,要具体看函数内容,新定义的变量不用考虑
# 出现未知变量调用方法时,要考虑传递参数的问题
"""发送数据"""
# 获取要发送的内容
dest_ip = input("请输入要发送目标的ip:")
dest_port = int(input("请输入要发送目标的port:"))
send_massage = input("请输入要发送的信息:")
udp_socket.sendto(send_massage.encode("utf-8"), (dest_ip, dest_port)) # 产生
# dest_ip,dest_port的需求,即在下方定义,定义完成后发现应该在前边进行定义,复制粘贴即可
def recv_data(udp_socket):
"""接收数据并显示"""
recv_data = udp_socket.recvfrom(1024) # recvfrom()方法返回的是一个元组类型
print("%s:%s" % (str(recv_data[1]), recv_data[0].decode("utf-8")))
# 除了与windows进行通信以外都用utf-8进行转化,windows用gbk.[1]代表元组内部第2部分
# 注意:一个具有独立功能的代码块要封装到一个函数之中
def main():
"""完成主要的主体流程"""
# 创建套接字
udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
# 创建完套接字,要想成功的接收到发送过来的信息,首先要有一个固定的端口号-绑定一个端口
# 绑定本地信息
udp_socket.bind(("",7788))
# while循环处理收发信息
while True:
# 发送:
send_data(udp_socket)
# 接收数据并显示
recv_data(udp_socket)
if __name__ == '__main__':
main()
10_案例:可控制操作
import socket
def send_data(udp_socket): # 定义成函数后,是否需要传参,要具体看函数内容,新定义的变量不用考虑
# 出现未知变量调用方法时,要考虑传递参数的问题
"""发送数据"""
# 获取要发送的内容
dest_ip = input("请输入要发送目标的ip:")
dest_port = int(input("请输入要发送目标的port:"))
send_massage = input("请输入要发送的信息:")
udp_socket.sendto(send_massage.encode("utf-8"), (dest_ip, dest_port)) # 产生
# dest_ip,dest_port的需求,即在下方定义,定义完成后发现应该在前边进行定义,复制粘贴即可
def recv_data(udp_socket):
"""接收数据并显示"""
recv_data = udp_socket.recvfrom(1024) # recvfrom()方法返回的是一个元组类型
print("%s:%s" % (str(recv_data[1]), recv_data[0].decode("utf-8")))
# 除了与windows进行通信以外都用utf-8进行转化,windows用gbk.[1]代表元组内部第2部分
# 注意:一个具有独立功能的代码块要封装到一个函数之中
def main():
"""完成主要的主体流程"""
# 创建套接字
udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
# 创建完套接字,要想成功的接收到发送过来的信息,首先要有一个固定的端口号-绑定一个端口
# 绑定本地信息
udp_socket.bind(("",7788))
# 若是不绑定,发送数据时系统会随机分配端口,在当次程序运行过程中,使用系统分配的端口可以实现消息回发
# while循环处理收发信息
while True:
"""用这样的方法以实现连续的收/发消息"""
print("*****洋仔聊天器*****")
print("1.发送消息")
print("2.接收消息")
print("0.退出系统")
it = input("请选择要使用的功能:")
if it == "1":
# 发送:
send_data(udp_socket)
elif it == "2":
# 接收数据并显示
recv_data(udp_socket)
elif it == "0":
break
else:
print("输入有误,请重新输入!")
if __name__ == '__main__':
main()
02_socket.tcp
01_tcp.client
import socket
def main():
# 1. 创建tcp套接字
tcp_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 此处若在路径中含有名为socket的文件,程序会出错,找不到AF_INET,导入模块的查找顺序是,
# 先从路径中寻找,没有再从系统中寻找.
# 使用SOCK_DGRAM创建套接字是创建的udp套接字,使用SOCK_STREAM创建的套接字是tcp套接字
# 2. 链接服务器
sever_ip = input("请输入服务器ip:")
sever_port = int(input("请输入服务器port:"))
# 这里一定要注意转换!
sever_addr = (sever_ip,sever_port)
tcp_socket.connect(sever_addr)
# tcp_socket.connect("192.168.146.130",8080)固定ip和port时,这一行代码等价于上边四行代码
# connect()方法内部是一个元组类型
# 3. 接收/发送数据
send_msg = input("请输入发送数据:")
tcp_socket.send(send_msg.encode("utf-8"))
# 此处使用的发送的方法是send 与sendto 的不同之处在于,他它只需要发送编码的信息即可,不
# 用再输入接收程序的端口信息,就像打电话一样,打过去之后说多少话都可以,不用再打一遍
# 4. 关闭套接字
tcp_socket.close()
if __name__ == "__main__":
main()
02_tcp.sever
import socket
def main():
# 1. 买个手机(创建一个套接字:socket)
tcp_sever_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 这个套接字是用来监听的
# 2. 插上手机卡(绑定本地信息:bind)
tcp_sever_socket.bind(("",7890))
# 3. 设置手机为正常接听状态(使套接字由主动变成被动套接字listen)
tcp_sever_socket.listen(128)
print("****1****")
# 4. 静待他人拨打电话(静待客户链接:accept)
new_client_socket,client_addr = tcp_sever_socket.accept() # 新的套接字标记着客户端
# 监听套接字默认会堵塞,一直堵塞到有一个新的客户端链接了你,就可以解堵塞,
# 并且解堵塞的时候会有一个元组类型的返回值,new_client_socket保存的是accept()
# 产生的新的套接字,client_addr保存客户端的信息
print(client_addr)
print("****2******")
# 服务器先收,客户端先发
# 接收客户端发送过来的数据
# 使用新的客户端调用接收和发送(就像拨打10086,是客服进行处理而不是总机)
recv_data = new_client_socket.recv(1024) # 和recvfeom很类似,返回值是表示接收数据的字节对象
# (一组数字b'\xe7\xbb\x99\xe6\x9e\xaa')。因为,client_addr
# 保存客户端的信息没有必要再一遍一遍的发送,而recvfrom内部还有谁发过来的信息
# 因为new_client_socket标记着客户端,知道客户端信息(ip,port)所以返回的时候仅仅有数据
print(recv_data)
print("发送过来的信息是:%s" % recv_data.decode("utf-8"))
# 回送一部分数据给客户端
new_client_socket.send("hahahahahaha*****ok****".encode("utf-8"))
# 关闭套接字
tcp_sever_socket.close()
new_client_socket.close()
# 创建了几个套接字就要关闭几个套接字
if __name__ == "__main__":
main()
03_循环为多个客户端服务的服务器
import socket
def main():
# 如同到银行办业务,领号,一个一个客户(客户端)接受服务(服务器)
# 1. 买个手机(创建一个套接字:socket)
tcp_sever_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 这个套接字是用来监听的
# 2. 插上手机卡(绑定本地信息:bind)
tcp_sever_socket.bind(("",7890))
# 3. 设置手机为正常接听状态(使套接字由主动变成被动套接字listen)
tcp_sever_socket.listen(128)
while True:
print("等待一个新的客户端的到来")
# 4. 静待人拨打电话(静待客户链接:accept)
new_client_socket,client_addr = tcp_sever_socket.accept() # 新的套接字标记着客户端
# 监听套接字默认会堵塞,一直堵塞到有一个新的客户端链接了你,就可以解堵塞,
# 并且解堵塞的时候会有一个元组类型的返回值,new_client_socket保存的是accept()
# 产生的新的套接字,client_addr保存客户端的信息
print("新来的客户端信息是:%s" % str(client_addr))
# 服务器先收,客户端先发
# 接收客户端发送过来的数据
# 使用新的客户端调用接收和发送(就像拨打10086,是客服进行处理而不是总机)
recv_data = new_client_socket.recv(1024) # 和recvfeom很类似,返回值是表示接收数据的字节对象
# (一组数字b'\xe7\xbb\x99\xe6\x9e\xaa')。因为,client_addr
# 保存客户端的信息没有必要再一遍一遍的发送,而recvfrom内部还有谁发过来的信息
# 因为new_client_socket标记着客户端,知道客户端信息(ip,port)所以返回的时候仅仅有数据
print(recv_data)
print("客户端发送过来的请求:%s" % recv_data.decode("utf-8"))
# 回送一部分数据给客户端
new_client_socket.send("hahahahahaha*****ok****".encode("utf-8"))
# 关闭套接字
# 关闭的是客户端的套接字,关闭accept()返回的套接字,意味着不会再为这个客户端服务
new_client_socket.close()
print("服务结束,欢迎下次光临!")
tcp_sever_socket.close()
# 如果将监听套接字关闭l,那么会导致不能再次等待新客户端的到来,即socket.accept()会失败
# 创建了几个套接字就要关闭几个套接字
if __name__ == "__main__":
main()
04_循环为多个客户端服务的服务器并且多次服务一个客户端
import socket
def main():
# 如同到银行办业务,领号,一个一个客户(客户端)接受服务(服务器)
# 为一个客户提供多次服务,就像拨打10086,必须由客户(客户端)挂断,客户端挂断后程序继续执行,等待新的客户端
# 1. 买个手机(创建一个套接字:socket)
tcp_sever_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 这个套接字是用来监听的
# 2. 插上手机卡(绑定本地信息:bind)
tcp_sever_socket.bind(("",7890))
# 3. 设置手机为正常接听状态(使套接字由主动变成被动套接字listen)
tcp_sever_socket.listen(128)
while True:
print("等待一个新的客户端的到来")
# 4. 静待人拨打电话(静待客户链接:accept)
new_client_socket,client_addr = tcp_sever_socket.accept() # 新的套接字标记着客户端
# 监听套接字默认会堵塞,一直堵塞到有一个新的客户端链接了你,就可以解堵塞,
# 并且解堵塞的时候会有一个元组类型的返回值,new_client_socket保存的是accept()
# 产生的新的套接字,client_addr保存客户端的信息
print("新来的客户端信息是:%s" % str(client_addr))
while True:
# 服务器先收,客户端先发
# 接收客户端发送过来的数据
# 使用新的客户端调用接收和发送(就像拨打10086,是客服进行处理而不是总机)
recv_data = new_client_socket.recv(1024) # 和recvfeom很类似,返回值是表示接收数据的字节对象
# (一组数字b'\xe7\xbb\x99\xe6\x9e\xaa')。因为,client_addr
# 保存客户端的信息没有必要再一遍一遍的发送,而recvfrom内部还有谁发过来的信息
# 因为new_client_socket标记着客户端,知道客户端信息(ip,port)所以返回的时候仅仅有数据
print(recv_data)
print("客户端发送过来的请求:%s" % recv_data.decode("utf-8"))
# 如果recv()解堵塞,那么有两种方式:
# 1.客户端发送过来数据
# 2.客户端调用close()从而导致了recv()解堵塞并且recv()的返回值为空
if recv_data:
# if 后边跟字符串,列表,元组...只要不空即为真,空为假
# 回送一部分数据给客户端
new_client_socket.send("hahahahahaha*****ok****".encode("utf-8"))
else:
break
# 程序内部有两个while True,一个break,break跳出的是离它最近的while True,与另一个一毛钱关系都没有
# 关闭套接字
# 关闭的是客户端的套接字,关闭accept()返回的套接字,意味着不会再为这个客户端服务
new_client_socket.close()
print("服务结束,欢迎下次光临!")
tcp_sever_socket.close()
# 如果将监听套接字关闭l,那么会导致不能再次等待新客户端的到来,即socket.accept()会失败
# 创建了几个套接字就要关闭几个套接字
if __name__ == "__main__":
main()
05_文件下载.client
import socket
def main():
"""客户端"""
# 1.创建套接字
tcp_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 2.获取服务器的ip和port
# 客户端可以不用绑定,一般也不绑定
sever_ip = input("输入服务器的ip:")
sever_port = int(input("请输入服务器的port:"))
# 3.链接服务器
# connect()方法内部是一个元组
tcp_socket.connect((sever_ip,sever_port))
# 4.获取下载的文件名字
download_file_name = input("请输入要下载的文件的名字:")
# 5.将文件名字发送给服务器
tcp_socket.send(download_file_name.encode("utf-8"))
# 6.接收文件中的数据
recv_file_data = tcp_socket.recv(1024*1024) # 1024--->1k 1024 * 1024--->1k * 1024 = 1M 1024 * 1024 * 1024 = 1g
# 7.保存接收的数据到一个文件中
if recv_file_data:
with open("附件" + download_file_name,"wb") as f:
# "+"表示字符串拼接;字符串+字符串:字符串拼接."w"表示以w(写)的方式打开;
# "b"表示以二进制的模式 .(之前的bytes类型其实就是二进制)
# 为什么要使用二进制的模式,因为recv()得到的数据就是二进制的数据,所以此处
# 使用二进制的方式打开,直接省去了先encode()再decode()过程
f.write(recv_file_data)
# 8.关闭套接字
tcp_socket.close()
pass
if __name__ == '__main__':
main()
06_文件下载.sever
import socket
def send_file_to_client(new_client_socket,client_addr):
# 1.接收客户端发送过来的要下载的文件名
file_name = new_client_socket.recv(1024).decode("utf-8")
print("客户端 %s 发送过来的要下载的文件名是:%s" % (str(client_addr),file_name))
# 2.打开这个文件,读取数据
# 此处不适合使用with因为with不仅是打开文件后发现异常会调用close()若打不开文件同样发现异常会调用close()
# with的前提是open()能够打开,打不开就挂了,如果用open的打开模式中有w,意味着写,写就意味着新建文件,
# 在有权限的前提下新建一个文件是不可能失败的
# 所以:若是新建一个文件,二话不说直接用with,但是要是以read的方式打开一个文件去为了读数据,这个文件是有不存在的可能的
# 故此处用try的方式
file_content = None # 给变量赋初始值
try:
f = open(file_name,"rb")
file_content = f.read()
# 打开以后定义一个变量将内容读取出来
f.close()
# 读完之后关闭文件
except Exception as ret:
# ret(result):是定义的变量,相当于定义了一个类Exception的对象
# Exception是针对异常提出塞外类
print("没有要下载的文件:%s " % file_name)
if file_content:
# 3.发送文件数据给客户端
new_client_socket.send(file_content)
# else:
# break 这样写为啥不对? 是因为上边exception已经进行错误监测了?
def main():
# 1. 买个手机(创建一个套接字:socket)
tcp_sever_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 这个套接字是用来监听的
# 2. 插上手机卡(绑定本地信息:bind)
tcp_sever_socket.bind(("",7890))
# 3. 设置手机为正常接听状态(使套接字由主动变成被动套接字listen)
tcp_sever_socket.listen(128)
while True:
# 4. 静待他人拨打电话(静待客户链接:accept)
new_client_socket,client_addr = tcp_sever_socket.accept()
# 5.调用发送文件函数,完成为客户端服务(由于这一部分功能独立,所以单独定义函数)
send_file_to_client(new_client_socket,client_addr)
# 6.1关闭客户端套接字
new_client_socket.close()
# 6.2关闭监听套接字
tcp_sever_socket.close()
# 创建了几个套接字就要关闭几个套接字
if __name__ == "__main__":
main()