Python使用socket传输文件
发布日期:2021-11-16 18:49:33
浏览次数:6
分类:技术文章
本文共 3823 字,大约阅读时间需要 12 分钟。
昨晚的高网实验要求用Socket编程实现两台机器的文件传输,还要记录传输时间并进行MD5验证,于是便用python简单实现了下。
过程其实挺简单,先建立两个进程的TCP连接,然后client先向server发送文件信息(包括文件名和文件大小以及MD5值),这个文件信息的大小是预先设定好的,也就是client和server都知道,这样server才能准确判断接收的数据哪些是文件信息哪些是真正的文件。这里用到了库对文件信息进行处理。这里的struct类似于c中的结构体,可以把变量转换成具有c结构体形式的字符串。比如我的例子中定义了这样一个struct形式:HEAD_STRUCT = '128sIq32s'
它就相当于c中如下结构体:
struct{ char fileName[128]; //文件名 int fileNameSize; //文件名长度 long long fileSize; //文件大小 char MD5[32]; //MD5值}
这个结构体的空间大小是固定的,于是当client按照这个格式发送文件信息的时候,server也以相同的格式接收信息。由于文件名的长度不固定,于是这里我还发送了一个文件名的长度,这样server就可以根据这个长度对fileName进行截取。
然后再发送文件,这里我是用1024B的缓冲区进行接收(最后一次小于或等于1024B)。# receiveimport socketimport hashlibimport structHOST = 'localhost'PORT = 1307BUFFER_SIZE = 1024HEAD_STRUCT = '128sIq32s'info_size = struct.calcsize(HEAD_STRUCT)def cal_md5(file_path): with open(file_path, 'rb') as fr: md5 = hashlib.md5() md5.update(fr.read()) md5 = md5.hexdigest() return md5def unpack_file_info(file_info): file_name, file_name_len, file_size, md5 = struct.unpack(HEAD_STRUCT, file_info) file_name = file_name[:file_name_len] return file_name, file_size, md5def recv_file(): try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_address = (HOST, PORT) sock.bind(server_address) sock.listen(1) client_socket, client_address = sock.accept() print "Connected %s successfully" % str(client_address) file_info_package = client_socket.recv(info_size) file_name, file_size, md5_recv = unpack_file_info(file_info_package) recved_size = 0 with open(file_name, 'wb') as fw: while recved_size < file_size: remained_size = file_size - recved_size recv_size = BUFFER_SIZE if remained_size > BUFFER_SIZE else remained_size recv_file = client_socket.recv(recv_size) recved_size += recv_size fw.write(recv_file) md5 = cal_md5(file_name) if md5 != md5_recv: print 'MD5 compared fail!' else: print 'Received successfully' except socket.errno, e: print "Socket error: %s" % str(e) finally: sock.close()if __name__ == '__main__': recv_file()
# sendimport socketimport osimport hashlibimport structHOST = 'localhost'PORT = 1307BUFFER_SIZE = 1024HEAD_STRUCT = '128sIq32s'def cal_md5(file_path): with open(file_path, 'rb') as fr: md5 = hashlib.md5() md5.update(fr.read()) md5 = md5.hexdigest() return md5def get_file_info(file_path): file_name = os.path.basename(file_path) file_name_len = len(file_name) file_size = os.path.getsize(file_path) md5 = cal_md5(file_path) return file_name, file_name_len, file_size, md5def send_file(file_path): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_address = (HOST, PORT) file_name, file_name_len, file_size, md5 = get_file_info(file_path) file_head = struct.pack(HEAD_STRUCT, file_name, file_name_len, file_size, md5) try: print "Start connect" sock.connect(server_address) sock.send(file_head) sent_size = 0 with open(file_path) as fr: while sent_size < file_size: remained_size = file_size - sent_size send_size = BUFFER_SIZE if remained_size > BUFFER_SIZE else remained_size send_file = fr.read(send_size) sent_size += send_size sock.send(send_file) except socket.errno, e: print "Socket error: %s" % str(e) finally: sock.close() print "Closing connect"if __name__ == '__main__': file_path = raw_input('Please input file path:') if not file_path: file_path = 'test.txt' send_file(file_path)
注意: - 在某些时候(比如传输大文件)会发生丢包的情况,这时候接收的文件大小会小于发送文件的大小,两个MD5值也会不一样。
转载地址:https://blog.csdn.net/Thare_Lam/article/details/49506565 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
能坚持,总会有不一样的收获!
[***.219.124.196]2024年03月29日 19时54分00秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
种树:二叉树、二叉搜索树、AVL树、红黑树、哈夫曼树、B树、树与森林
2021-06-30
【C++】攻克哈希表(unordered_map)
2021-06-30
转:【答学员问】- 该如何根据岗位学习相关技能
2021-06-30
转:【答学员问】有什么经验教训,是你在面试很多次之后才知道的?
2021-06-30
消息队列:解耦、异步、削峰,现有MQ对比以及新手入门该如何选择MQ?
2021-06-30
【奇技淫巧】-- 三角形最小路径和
2021-06-30
【小技巧】argc和argv的用法
2021-06-30
学不下去了怎么办?
2021-06-30
二叉树的前中后序遍历(迭代法)(带动画)
2021-06-30
【小技巧】【XShell】【Xftp】Windows桌面与Linux虚拟机互传文件
2021-06-30
【redis入门】Centos下安装redis
2021-06-30
【redis入门】redis安装后相关知识串讲
2021-06-30
【redis】来吧,展示一下redis 发布-订阅模式
2021-06-30
当下热点词再学:redis缓存预热、更新、降级,限流
2021-06-30
【redis6.0.6】redis源码慢慢学,慢慢看 -- 第五天:adlist
2021-06-30
别抖,OK? 操作系统抖动现象、网络抖动与延迟、函数抖动之防抖与节流,串讲
2021-06-30
通过域名获取主机IP -- struct addrinfo
2021-06-30