python cs架構(gòu)實現(xiàn)簡單文件傳輸
本文為大家分享了python cs架構(gòu)實現(xiàn)簡單文件的傳輸代碼,供大家參考,具體內(nèi)容如下
要實現(xiàn)簡單文件的傳輸我們必須考慮這些問題:
1.什么是c/s架構(gòu)?
顧名思義,就是客戶端端/服務器架構(gòu)。不同的人可能回答不一,但是有一點是相同的:服務器是一個軟件或硬件,用于向一個或多個客戶端提供所需要的服務,服務器存在的唯一目的就是等待客戶的請求,給這些客戶服務,然后等待其他的請求。
2.客戶端與服務端如何通信?
其實說白了就是互聯(lián)網(wǎng)中兩個主機該如何通信,首先我們用ip地址可以標示一臺主機,這樣就可以通信了么?當然也不行,我們還得標示主機中的進程,當然協(xié)議也是不可或缺的,是udp報文協(xié)議還是tcp數(shù)據(jù)流協(xié)議,這的看你個人的需求。用套介子來作為一個標示符,唯一標識網(wǎng)絡進程。
想明白這兩個問題我覺得這個問題有三分之一已經(jīng)解決了,接下來呢我選擇tcp協(xié)議來傳輸。
服務端:
采用socket()函數(shù) 定義socket描述字
bind()函數(shù)來把地址族中一個特定地址賦給socket,簡單來說就是把一個ipv4/ipv6地址+端口號組合賦給socket
listen()函數(shù)把socket變成被動類型的,等待客戶連接請求。
當客戶端發(fā)來消息時用accept()函數(shù)來接受請求,同時給服務端返回客戶端的socket描述字,接下來服務端以接收到的描述字來向客戶端發(fā)送信息以及接受信息。
我們這個程序是實現(xiàn)文件傳輸,我的想法是類似于ftp程序接受客戶上傳下載文件的需求。服務端啟動后監(jiān)聽端口(我用的9500)等待客戶連接??蛻舳巳挝帐纸⑦B接后,客戶輸入命令來向客戶端發(fā)起請求,輸入‘ls'命令可以查看服務端可下載的文件,輸入‘put 文件名',‘get 文件名'可以上傳下載文件。上傳文件時客戶端打開本地文件以二進制方式讀取文件內(nèi)容并同時調(diào)用send()函數(shù)發(fā)送文件內(nèi)容,服務端以寫方式打開文件并將客戶端上傳內(nèi)容寫入文件,實現(xiàn)文件的上傳。下載文件與此類似,客戶端上傳送‘get 文件名'命令同時以寫方式打開文件 ,服務端收到命令以讀方式打開文件,并發(fā)送給服務端。
tcp三次握手建立連接:
當客戶端調(diào)用connect時,觸發(fā)了連接請求,向服務器發(fā)送了SYN J包,這時connect進入阻塞狀態(tài);服務器監(jiān)聽到連接請求,即收到SYN J包,調(diào)用accept函 數(shù)接收請求向客戶端發(fā)送SYN K ,ACK J+1,這時accept進入阻塞狀態(tài);客戶端收到服務器的SYN K ,ACK J+1之后,這時connect返回,并對SYN K進行確認;服務器收到ACK K+1時,accept返回,至此三次握手完畢,連接建立。
tcp四次揮手斷開連接:
某個應用進程首先調(diào)用close主動關閉連接,這時TCP發(fā)送一個FIN M;另一端接收到FIN M之后,執(zhí)行被動關閉,對這個FIN進行確認。它的接收也作為文件結(jié)束符傳遞給應用進程,因為FIN的接收意味著應用進程在相應的連接上再也接收不到額外數(shù)據(jù);一段時間之后,接收到文件結(jié)束符的應用進程調(diào)用close關閉它的socket。這導致它的TCP也發(fā)送一個FIN N;接收到這個FIN的源發(fā)送端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()
運行截圖:
服務端:
客戶端:
歡迎各位大牛,多提寶貴意見。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
- Python實現(xiàn)基于HTTP文件傳輸實例
- Python實現(xiàn)的簡單文件傳輸服務器和客戶端
- python實現(xiàn)的一個p2p文件傳輸實例
- python使用tcp實現(xiàn)局域網(wǎng)內(nèi)文件傳輸
- python3.5基于TCP實現(xiàn)文件傳輸
- python 使用poster模塊進行http方式的文件傳輸?shù)椒掌鞯姆椒?/a>
- 樹莓派采用socket方式文件傳輸(python)
- python基于xmlrpc實現(xiàn)二進制文件傳輸?shù)姆椒?/a>
- python實現(xiàn)FTP文件傳輸?shù)姆椒ǎǚ掌鞫撕涂蛻舳耍?/a>
- python利用socket實現(xiàn)udp文件傳輸功能
相關文章
Python實現(xiàn)網(wǎng)絡端口轉(zhuǎn)發(fā)和重定向的方法
這篇文章主要介紹了Python實現(xiàn)網(wǎng)絡端口轉(zhuǎn)發(fā)和重定向的方法,結(jié)合實例形式分析了Python基于threading和socket模塊實現(xiàn)端口轉(zhuǎn)發(fā)與重定向的具體操作技巧,需要的朋友可以參考下2016-09-09python 如何用map()函數(shù)創(chuàng)建多線程任務
這篇文章主要介紹了python 使用map()函數(shù)創(chuàng)建多線程任務的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-04-04詳解利用Pandas求解兩個DataFrame的差集,交集,并集
這篇文章主要和大家講解一下如何利用Pandas函數(shù)求解兩個DataFrame的差集、交集、并集,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下2022-07-07Python中l(wèi)ist列表的賦值方法及遇到問題處理
這篇文章主要介紹了Python中l(wèi)ist列表的賦值方法及遇到問題處理,記錄在列表list的賦值過程中遇到的問題,并對列表的拷貝相關知識進行匯總,需要的朋友可以參考一下2022-03-03