Python使用socket传输文件
来源:互联网 发布:天涯明月刀情缘 知乎 编辑:程序博客网 时间:2024/05/17 09:01
昨晚的高网实验要求用Socket编程实现两台机器的文件传输,还要记录传输时间并进行MD5验证,于是便用python简单实现了下。
过程其实挺简单,先建立两个进程的TCP连接,然后client先向server发送文件信息(包括文件名和文件大小以及MD5值),这个文件信息的大小是预先设定好的,也就是client和server都知道,这样server才能准确判断接收的数据哪些是文件信息哪些是真正的文件。这里用到了struct库对文件信息进行处理。这里的struct类似于c中的结构体,可以把变量转换成具有c结构体形式的字符串。比如我的例子中定义了这样一个struct形式:
HEAD_STRUCT = '128sIq32s'
它就相当于c中如下结构体:
struct{ char fileName[128]; int fileNameSize; long long fileSize; char MD5[32];}
这个结构体的空间大小是固定的,于是当client按照这个格式发送文件信息的时候,server也以相同的格式接收信息。由于文件名的长度不固定,于是这里我还发送了一个文件名的长度,这样server就可以根据这个长度对fileName进行截取。
然后再发送文件,这里我是用1024B的缓冲区进行接收(最后一次小于或等于1024B)。
***server.py***import socketimport structimport hashlibHOST = 'localhost'PORT = 1307BUFFER_SIZE = 1024HEAD_STRUCT = '128sIq32s' # Structure of file headdef recv_file(): # Create a TCP socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Enable reuse address/port # sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # Bind the socket to the port server_address = (HOST, PORT) # Bind server address sock.bind(server_address) print "Starting server on %s port %s" % server_address # Listen to clients sock.listen(1) print "Waiting to receive from client" client_socket, client_address = sock.accept() print "Socket %s:%d has connect" % client_address # Receive file info info_struct = struct.calcsize(HEAD_STRUCT) file_info = client_socket.recv(info_struct) file_name2, filename_size, file_size, md5_recv = struct.unpack(HEAD_STRUCT, file_info) file_name = file_name2[:filename_size] fw = open(file_name, 'wb') recv_size = 0 print "Receiving data..." while (recv_size < file_size): if(file_size - recv_size < BUFFER_SIZE): file_data = client_socket.recv(file_size - recv_size) recv_size = file_size else: file_data = client_socket.recv(BUFFER_SIZE) recv_size += BUFFER_SIZE fw.write(file_data) fw.close() print "Accept success!" print "Calculating MD5..." fw = open(file_name, 'rb') md5_cal = hashlib.md5() md5_cal.update(fw.read()) print " Recevie MD5 : %s" %md5_recv print "Calculate MD5 : %s" % md5_cal.hexdigest() fw.close()if __name__ == '__main__': recv_file()
***client.py***import socketimport structimport osimport timeimport hashlibHOST = 'localhost'PORT = 1307BUFFER_SIZE = 1024FILE_NAME = '001.dmg' # Change to your fileFILE_SIZE = os.path.getsize(FILE_NAME)HEAD_STRUCT = '128sIq32s' # Structure of file headdef send_file(): # Create a TCP/IP socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Connect the socket to the server server_address = (HOST, PORT) #Calculate MD5 print "Calculating MD5..." fr = open(FILE_NAME, 'rb') md5_code = hashlib.md5() md5_code.update(fr.read()) fr.close() print "Calculating success" # Need open again fr = open(FILE_NAME, 'rb') # Pack file info(file name and file size) file_head = struct.pack(HEAD_STRUCT, FILE_NAME, len(FILE_NAME), FILE_SIZE, md5_code.hexdigest()) try: # Connect sock.connect(server_address) print "Connecting to %s port %s" % server_address # Send file info sock.send(file_head) send_size = 0 print "Sending data..." time_start = time.time() while(send_size < FILE_SIZE): if(FILE_SIZE - send_size < BUFFER_SIZE): file_data = fr.read(FILE_SIZE - send_size) send_size = FILE_SIZE else: file_data = fr.read(BUFFER_SIZE) send_size += BUFFER_SIZE sock.send(file_data) time_end = time.time() print "Send success!" print "MD5 : %s" % md5_code.hexdigest() print "Cost %f seconds" % (time_end - time_start) fr.close() sock.close() except socket.errno, e: print "Socket error: %s" % str(e) except Exception, e: print "Other exception : %s" % str(e) finally: print "Closing connect"if __name__ == '__main__': send_file()
注意: - 在使用的时候可把server和client放在两个不同文件夹下,待发文件和client放在同一文件夹下,client.py中的FILE_NAME需要修改成待发的文件名。 - 在某些时候(比如传输大文件)会发生丢包的情况,这时候接收的文件大小会小于发送文件的大小,两个MD5值也会不一样。
0 0
- Python使用socket传输文件
- python使用tcp socket 传输文件-服务端,客户端
- Java使用Socket传输文件
- python实现用socket传输文件
- python 间谍程序传输文件 socket编程
- python实现用socket传输文件
- 使用Socket实现文件的传输
- VC++使用Socket网络编程传输文件
- 通过缓冲区使用socket传输文件
- Java Socket实战之七 使用Socket通信传输文件
- Java Socket实战之七 使用Socket通信传输文件
- Java Socket实战之七 使用Socket通信传输文件
- Java Socket实战之七 使用Socket通信传输文件
- Java Socket实战之七 使用Socket通信传输文件
- Java Socket实战之七 使用Socket通信传输文件
- Java Socket实战之七 使用Socket通信传输文件
- Java Socket实战之七 使用Socket通信传输文件
- Java Socket实战之七 使用Socket通信传输文件
- 稀疏矩阵的三元组表示的实现及应用(2)——采用三元组存储稀疏矩阵,设计两个稀疏矩阵相加的运算算法
- 第九周-项目2 - 对称矩阵压缩存储的实现与应用
- 图文解说 JavaScript this 到底指向什么?
- dlopen RTLD_NOW RTLD_LAZY RTLD_GLOBAL
- maven常用命令
- Python使用socket传输文件
- 浅谈XML 解析技术性能对比分析之 解析XML
- 12 个 CSS 高级技巧汇总
- 全面理解Unity加载和内存管理机制之二:进一步深入和细节
- LintCode_子数组之和
- mysql 日期转换
- Algorithms—11.Container With Most Water
- Android EditText 不可编辑到可编辑状态改变
- Spring Security教程(1)----SpringSecurity3.2环境搭建