python cs架構(gòu)實(shí)現(xiàn)簡單文件傳輸
本文為大家分享了python cs架構(gòu)實(shí)現(xiàn)簡單文件的傳輸代碼,供大家參考,具體內(nèi)容如下
要實(shí)現(xiàn)簡單文件的傳輸我們必須考慮這些問題:
1.什么是c/s架構(gòu)?
顧名思義,就是客戶端端/服務(wù)器架構(gòu)。不同的人可能回答不一,但是有一點(diǎn)是相同的:服務(wù)器是一個(gè)軟件或硬件,用于向一個(gè)或多個(gè)客戶端提供所需要的服務(wù),服務(wù)器存在的唯一目的就是等待客戶的請求,給這些客戶服務(wù),然后等待其他的請求。
2.客戶端與服務(wù)端如何通信?
其實(shí)說白了就是互聯(lián)網(wǎng)中兩個(gè)主機(jī)該如何通信,首先我們用ip地址可以標(biāo)示一臺(tái)主機(jī),這樣就可以通信了么?當(dāng)然也不行,我們還得標(biāo)示主機(jī)中的進(jìn)程,當(dāng)然協(xié)議也是不可或缺的,是udp報(bào)文協(xié)議還是tcp數(shù)據(jù)流協(xié)議,這的看你個(gè)人的需求。用套介子來作為一個(gè)標(biāo)示符,唯一標(biāo)識(shí)網(wǎng)絡(luò)進(jìn)程。
想明白這兩個(gè)問題我覺得這個(gè)問題有三分之一已經(jīng)解決了,接下來呢我選擇tcp協(xié)議來傳輸。
服務(wù)端:
采用socket()函數(shù) 定義socket描述字
bind()函數(shù)來把地址族中一個(gè)特定地址賦給socket,簡單來說就是把一個(gè)ipv4/ipv6地址+端口號(hào)組合賦給socket
listen()函數(shù)把socket變成被動(dòng)類型的,等待客戶連接請求。
當(dāng)客戶端發(fā)來消息時(shí)用accept()函數(shù)來接受請求,同時(shí)給服務(wù)端返回客戶端的socket描述字,接下來服務(wù)端以接收到的描述字來向客戶端發(fā)送信息以及接受信息。
我們這個(gè)程序是實(shí)現(xiàn)文件傳輸,我的想法是類似于ftp程序接受客戶上傳下載文件的需求。服務(wù)端啟動(dòng)后監(jiān)聽端口(我用的9500)等待客戶連接??蛻舳巳挝帐纸⑦B接后,客戶輸入命令來向客戶端發(fā)起請求,輸入‘ls'命令可以查看服務(wù)端可下載的文件,輸入‘put 文件名',‘get 文件名'可以上傳下載文件。上傳文件時(shí)客戶端打開本地文件以二進(jìn)制方式讀取文件內(nèi)容并同時(shí)調(diào)用send()函數(shù)發(fā)送文件內(nèi)容,服務(wù)端以寫方式打開文件并將客戶端上傳內(nèi)容寫入文件,實(shí)現(xiàn)文件的上傳。下載文件與此類似,客戶端上傳送‘get 文件名'命令同時(shí)以寫方式打開文件 ,服務(wù)端收到命令以讀方式打開文件,并發(fā)送給服務(wù)端。
tcp三次握手建立連接:

當(dāng)客戶端調(diào)用connect時(shí),觸發(fā)了連接請求,向服務(wù)器發(fā)送了SYN J包,這時(shí)connect進(jìn)入阻塞狀態(tài);服務(wù)器監(jiān)聽到連接請求,即收到SYN J包,調(diào)用accept函 數(shù)接收請求向客戶端發(fā)送SYN K ,ACK J+1,這時(shí)accept進(jìn)入阻塞狀態(tài);客戶端收到服務(wù)器的SYN K ,ACK J+1之后,這時(shí)connect返回,并對SYN K進(jìn)行確認(rèn);服務(wù)器收到ACK K+1時(shí),accept返回,至此三次握手完畢,連接建立。
tcp四次揮手?jǐn)嚅_連接:

某個(gè)應(yīng)用進(jìn)程首先調(diào)用close主動(dòng)關(guān)閉連接,這時(shí)TCP發(fā)送一個(gè)FIN M;另一端接收到FIN M之后,執(zhí)行被動(dòng)關(guān)閉,對這個(gè)FIN進(jìn)行確認(rèn)。它的接收也作為文件結(jié)束符傳遞給應(yīng)用進(jìn)程,因?yàn)镕IN的接收意味著應(yīng)用進(jìn)程在相應(yīng)的連接上再也接收不到額外數(shù)據(jù);一段時(shí)間之后,接收到文件結(jié)束符的應(yīng)用進(jìn)程調(diào)用close關(guān)閉它的socket。這導(dǎo)致它的TCP也發(fā)送一個(gè)FIN N;接收到這個(gè)FIN的源發(fā)送端TCP對它進(jìn)行確認(rèn)。
服務(wù)端代碼:
#!/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()
運(yùn)行截圖:
服務(wù)端:

客戶端:

歡迎各位大牛,多提寶貴意見。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Python實(shí)現(xiàn)基于HTTP文件傳輸實(shí)例
- Python實(shí)現(xiàn)的簡單文件傳輸服務(wù)器和客戶端
- python實(shí)現(xiàn)的一個(gè)p2p文件傳輸實(shí)例
- python使用tcp實(shí)現(xiàn)局域網(wǎng)內(nèi)文件傳輸
- python3.5基于TCP實(shí)現(xiàn)文件傳輸
- python 使用poster模塊進(jìn)行http方式的文件傳輸?shù)椒?wù)器的方法
- 樹莓派采用socket方式文件傳輸(python)
- python基于xmlrpc實(shí)現(xiàn)二進(jìn)制文件傳輸?shù)姆椒?/a>
- python實(shí)現(xiàn)FTP文件傳輸?shù)姆椒ǎǚ?wù)器端和客戶端)
- python利用socket實(shí)現(xiàn)udp文件傳輸功能
相關(guān)文章
Python使用正則實(shí)現(xiàn)計(jì)算字符串算式
這篇文章主要介紹了Python使用正則實(shí)現(xiàn)計(jì)算字符串算式的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-12-12
django執(zhí)行原生SQL查詢的實(shí)現(xiàn)
本文主要介紹了django執(zhí)行原生SQL查詢的實(shí)現(xiàn),主要有兩種方法實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08
Pytorch中使用ImageFolder讀取數(shù)據(jù)集時(shí)忽略特定文件
這篇文章主要介紹了Pytorch中使用ImageFolder讀取數(shù)據(jù)集時(shí)忽略特定文件,具有一的參考價(jià)值需要的小伙伴可以參考一下,希望對你有所幫助2022-03-03
PyTorch中view()與?reshape()的區(qū)別詳析
這篇文章主要給大家介紹了關(guān)于PyTorch中view()?與?reshape()?區(qū)別的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-01-01
Python 普通最小二乘法(OLS)進(jìn)行多項(xiàng)式擬合的方法
今天小編就為大家分享一篇Python 普通最小二乘法(OLS)進(jìn)行多項(xiàng)式擬合的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-12-12
Python OpenCV實(shí)戰(zhàn)之與機(jī)器學(xué)習(xí)的碰撞
機(jī)器學(xué)習(xí)是人工智能的子集,為計(jì)算機(jī)以及其它具有計(jì)算能力的系統(tǒng)提供自動(dòng)預(yù)測或決策的能力。本文主要介紹了OpenCV 提供的常見機(jī)器學(xué)習(xí)算法和技術(shù),用于解決計(jì)算機(jī)視覺項(xiàng)目中的實(shí)際問題,需要的朋友可以參考一下2021-12-12
基于Python實(shí)現(xiàn)植物大戰(zhàn)僵尸游戲的示例代碼
植物大戰(zhàn)僵尸是一款經(jīng)典的塔防類游戲,玩家通過種植各種植物來抵御僵尸的攻擊,本文將詳細(xì)介紹如何使用Python和Pygame庫來實(shí)現(xiàn)一個(gè)簡單的植物大戰(zhàn)僵尸游戲,文中通過代碼示例講解的非常詳細(xì),感興趣的小伙伴跟著小編一起來看看吧2024-10-10
Python構(gòu)建一個(gè)文檔掃描器的實(shí)現(xiàn)
本文主要介紹了Python構(gòu)建一個(gè)文檔掃描器的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03

