自学python实例_从tcp服务器简单下载一下文件的实例

想象一下,我们平时下文件的时候和在qq上聊天的时候,有什么异同呢?都是接收文件是吧?只是一个小一点,一个大一点,那么如果我们的文件变成很小,是不是可以认为也是聊天的一种形式呢?
自学python实例_tcp服务器
自学python实例_udp聊天窗口
这上面是之前写的,分别是用tcp和udp实现的一些简单的聊天窗口!
那么今天,我们改进一下,我们对tcp服务器来下载一个文件!
向上代码!

import socket
def send_file_2_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))
	file_content = None
	# 2. 打开这个文件, 读取数据
	try:
		f = open(file_name, "rb")
		file_content = f.read()
		f.close()
	except Exception as ret:
		print("没有要下载的文件 %s" % file_name)
	# 3. 发送文件的数据给客户端
	if file_content:
		#new_client_socket.send("发送完毕".encode("utf-8"))
		new_client_socket.send(file_content)
def main():
	# 1. 创建套接字
	tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	# 2. 绑定本地信息
	tcp_server_socket.bind(("",7799))
	# 3. 设为被动
	tcp_server_socket.listen(128)
	while True:
		# 4. 等等对方进来
		new_client_socket, client_addr = tcp_server_socket.accept()
		# 5. 发送数据
		send_file_2_client(new_client_socket, client_addr)
		# 5. 关闭套接字
		new_client_socket.close
	cp_server_socket.close()
if __name__ == "__main__":
	main()

因为代码不是长,所有减少了一些缩进,因此没有完全遵循PEP8编码规范!
创建套节字…绑定…设监听…接堵塞…这个跳过,是基本的.
主要说 def send_file_2_client(new_client_socket, client_addr):这个函数,注意里面,我们打开文件使用了try是为什么呢?
是保证我们文件能正常打开并且写入,如果不成功,会告诉客户端没有要下载的文件.我们想象一下,如果没有try当我们在读写过程中,程序突然奔溃了,那么就不会调用f.close(),会导致这个文件占我们内存,注意了我们最多可以打开1024个文件,如果打开了很多文件,并且没有关闭,那么就会造成系统的奔溃!!
处理使用try之外,我们还可以使用 with 上下文管理器!!

with open("file_name, "rb") as f:
	f.write("file_content")

将上面替换成这个就可以了!使用with时,当程序突然奔溃的时候,或者结束了,都会主动调用f.close()
那么它是如何实现的呢,我们简单模拟一下:

class File():
	def __init__(self, file_name, mode):
		self.file_name = file_name
		self.mode = mode
	def __enter__(self):
		print("entering")
		self.f = open(sekf.file_name, self.mode)
		return self.f
	def __exit__(self, *args):
		print("exit")
		self.f.close()

内部可以大致模拟成这样,当出问题的时候,会主动调用类方法__exit___()
当然,上下文管理器还有另一种方式,使用contextmanager的装饰器来实现,这里我简单列举一下代码

from contextlib import contextmanager

@contextmanager
def my_open(path, mode):
	f = open(path, mode)
	yield f
	f.close()

通过yield将函数分成了两个部分,yield之前的语句是__enter__方法中执行的,yield之后的语句是__exit__方法中执行的,紧跟着的值是这个函数的返回值!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值