python cs架构实现简单文件传输
本文为大家分享了python cs架构实现简单文件的传输代码,供大家参考,具体内容如下
要实现简单文件的传输我们必须考虑这些问题:
1.什么是c/s架构?
顾名思义,就是客户端端/服务器架构。不同的人可能回答不一,但是有一点是相同的:服务器是一个软件或硬件,用于向一个或多个客户端提供所需要的服务,服务器存在的唯一目的就是等待客户的请求,给这些客户服务,然后等待其他的请求。
2.客户端与服务端如何通信?
其实说白了就是互联网中两个主机该如何通信,首先我们用ip地址可以标示一台主机,这样就可以通信了么?当然也不行,我们还得标示主机中的进程,当然协议也是不可或缺的,是udp报文协议还是tcp数据流协议,这的看你个人的需求。用套介子来作为一个标示符,唯一标识网络进程。
想明白这两个问题我觉得这个问题有三分之一已经解决了,接下来呢我选择tcp协议来传输。
服务端:
采用socket()函数 定义socket描述字
bind()函数来把地址族中一个特定地址赋给socket,简单来说就是把一个ipv4/ipv6地址+端口号组合赋给socket
listen()函数把socket变成被动类型的,等待客户连接请求。
当客户端发来消息时用accept()函数来接受请求,同时给服务端返回客户端的socket描述字,接下来服务端以接收到的描述字来向客户端发送信息以及接受信息。
我们这个程序是实现文件传输,我的想法是类似于ftp程序接受客户上传下载文件的需求。服务端启动后监听端口(我用的9500)等待客户连接。客户端三次握手建立连接后,客户输入命令来向客户端发起请求,输入‘ls'命令可以查看服务端可下载的文件,输入‘put 文件名',‘get 文件名'可以上传下载文件。上传文件时客户端打开本地文件以二进制方式读取文件内容并同时调用send()函数发送文件内容,服务端以写方式打开文件并将客户端上传内容写入文件,实现文件的上传。下载文件与此类似,客户端上传送‘get 文件名'命令同时以写方式打开文件 ,服务端收到命令以读方式打开文件,并发送给服务端。
tcp三次握手建立连接:
当客户端调用connect时,触发了连接请求,向服务器发送了SYN J包,这时connect进入阻塞状态;服务器监听到连接请求,即收到SYN J包,调用accept函 数接收请求向客户端发送SYN K ,ACK J+1,这时accept进入阻塞状态;客户端收到服务器的SYN K ,ACK J+1之后,这时connect返回,并对SYN K进行确认;服务器收到ACK K+1时,accept返回,至此三次握手完毕,连接建立。
tcp四次挥手断开连接:
某个应用进程首先调用close主动关闭连接,这时TCP发送一个FIN M;另一端接收到FIN M之后,执行被动关闭,对这个FIN进行确认。它的接收也作为文件结束符传递给应用进程,因为FIN的接收意味着应用进程在相应的连接上再也接收不到额外数据;一段时间之后,接收到文件结束符的应用进程调用close关闭它的socket。这导致它的TCP也发送一个FIN N;接收到这个FIN的源发送端TCP对它进行确认。
服务端代码:
#!/usr/bin/env python from socket import * import time import sys import os HOST = 'localhost' PORT = 9500 BUFIZ = 1024 ADDR = (HOST,PORT) def recvfile(filename): print 'starting receive file...' f = open(filename,'wb') cliSockfd.send('no problem') while True: data = cliSockfd.recv(4096) if data == 'EOF': print 'recved file success!' break f.write(data) f.close() def sendfile(filename): print 'starting send file...' cliSockfd.send('no problem') f = open(filename,'rb') while True: data = f.read(4096) if not data: break cliSockfd.send(data) f.close() time.sleep(1) cliSockfd.send('EOF') print 'send file success!' def handle1(act,filename): if act == 'put': print 'recving msg!' recvfile(filename) elif act == 'get': print 'sending msg!' sendfile(filename) else: print 'error!' def handle2(act): if act == 'ls': path = sys.path[0] every_file = os.listdir(path) for filename in every_file: cliSockfd.send(filename + ' ') time.sleep(1) cliSockfd.send('EOF') print 'all filename has send to client success!' else: print 'command error' sockfd = socket(AF_INET,SOCK_STREAM) sockfd.bind(ADDR) sockfd.listen(5) while True: print 'waiting for connection...' cliSockfd,addr = sockfd.accept() print '...connected from:',addr while True: msg = cliSockfd.recv(4096) if msg == 'close': print 'client closed' break info = msg.split() if len(info) == 2: handle1(*info) elif len(info) == 1: handle2(*info) else: print 'command error!' break
客户端代码:
#!/usr/bin/env python import sys import socket import time HOST = 'localhost' PORT = 9500 BUFSIZ = 1024 ADDR = (HOST,PORT) cliSockfd = socket.socket(socket.AF_INET,socket.SOCK_STREAM) def recvfile(filename): f = open(filename,'wb') while True: msg = cliSockfd.recv(4096) if msg == 'EOF': print 'recv file success!' break f.write(msg) f.close def sendfile(filename): f = open(filename,'rb') while True: msg = f.read(4096) if not msg: break cliSockfd.sendall(msg) f.close() time.sleep(1) cliSockfd.sendall('EOF') print 'send file success' def confirm(cliSockfd,client_command): cliSockfd.send(client_command) msg = cliSockfd.recv(4096) if msg == 'no problem': return True def handle1(act,filename): if act == 'put': if confirm(cliSockfd,client_command): sendfile(filename) else: print 'server error1!' elif act == 'get': if confirm(cliSockfd,client_command): recvfile(filename) else: print 'server error2!' else: print 'command error!' def handle2(act): if act == 'ls': cliSockfd.send('ls') while True: msg = cliSockfd.recv(1024) if msg == 'EOF': break print msg else: print 'command error' try: cliSockfd.connect(ADDR) print 'connect to ',ADDR while True: client_command = raw_input('>>>') if not client_command: continue msg = client_command.split() if len(msg) == 2: handle1(*msg) elif len(msg) == 1 and msg != ['close']: handle2(*msg) elif len(msg) == 1 and msg == ['close']: cliSockfd.send('close') break else: print 'command error' except socket.error,e: print 'error:',e finally: cliSockfd.close()
运行截图:
服务端:
客户端:
欢迎各位大牛,多提宝贵意见。