溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

python cs架構(gòu)實(shí)現(xiàn)簡(jiǎn)單文件傳輸

發(fā)布時(shí)間:2020-10-13 04:59:58 來(lái)源:腳本之家 閱讀:297 作者:AbnerKou 欄目:開(kāi)發(fā)技術(shù)

本文為大家分享了python cs架構(gòu)實(shí)現(xiàn)簡(jiǎn)單文件的傳輸代碼,供大家參考,具體內(nèi)容如下

要實(shí)現(xiàn)簡(jiǎn)單文件的傳輸我們必須考慮這些問(wèn)題:

1.什么是c/s架構(gòu)?

顧名思義,就是客戶端端/服務(wù)器架構(gòu)。不同的人可能回答不一,但是有一點(diǎn)是相同的:服務(wù)器是一個(gè)軟件或硬件,用于向一個(gè)或多個(gè)客戶端提供所需要的服務(wù),服務(wù)器存在的唯一目的就是等待客戶的請(qǐng)求,給這些客戶服務(wù),然后等待其他的請(qǐng)求。

2.客戶端與服務(wù)端如何通信?

其實(shí)說(shuō)白了就是互聯(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è)人的需求。用套介子來(lái)作為一個(gè)標(biāo)示符,唯一標(biāo)識(shí)網(wǎng)絡(luò)進(jìn)程。

想明白這兩個(gè)問(wèn)題我覺(jué)得這個(gè)問(wèn)題有三分之一已經(jīng)解決了,接下來(lái)呢我選擇tcp協(xié)議來(lái)傳輸。

服務(wù)端:

        采用socket()函數(shù) 定義socket描述字

        bind()函數(shù)來(lái)把地址族中一個(gè)特定地址賦給socket,簡(jiǎn)單來(lái)說(shuō)就是把一個(gè)ipv4/ipv6地址+端口號(hào)組合賦給socket

        listen()函數(shù)把socket變成被動(dòng)類型的,等待客戶連接請(qǐng)求。

        當(dāng)客戶端發(fā)來(lái)消息時(shí)用accept()函數(shù)來(lái)接受請(qǐng)求,同時(shí)給服務(wù)端返回客戶端的socket描述字,接下來(lái)服務(wù)端以接收到的描述字來(lái)向客戶端發(fā)送信息以及接受信息。

        我們這個(gè)程序是實(shí)現(xiàn)文件傳輸,我的想法是類似于ftp程序接受客戶上傳下載文件的需求。服務(wù)端啟動(dòng)后監(jiān)聽(tīng)端口(我用的9500)等待客戶連接。客戶端三次握手建立連接后,客戶輸入命令來(lái)向客戶端發(fā)起請(qǐng)求,輸入‘ls'命令可以查看服務(wù)端可下載的文件,輸入‘put   文件名',‘get  文件名'可以上傳下載文件。上傳文件時(shí)客戶端打開(kāi)本地文件以二進(jìn)制方式讀取文件內(nèi)容并同時(shí)調(diào)用send()函數(shù)發(fā)送文件內(nèi)容,服務(wù)端以寫方式打開(kāi)文件并將客戶端上傳內(nèi)容寫入文件,實(shí)現(xiàn)文件的上傳。下載文件與此類似,客戶端上傳送‘get  文件名'命令同時(shí)以寫方式打開(kāi)文件 ,服務(wù)端收到命令以讀方式打開(kāi)文件,并發(fā)送給服務(wù)端。

tcp三次握手建立連接:

python cs架構(gòu)實(shí)現(xiàn)簡(jiǎn)單文件傳輸

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

tcp四次揮手?jǐn)嚅_(kāi)連接:

python cs架構(gòu)實(shí)現(xiàn)簡(jiǎ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)閉,對(duì)這個(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對(duì)它進(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ù)端:

python cs架構(gòu)實(shí)現(xiàn)簡(jiǎn)單文件傳輸

客戶端:

python cs架構(gòu)實(shí)現(xiàn)簡(jiǎn)單文件傳輸

歡迎各位大牛,多提寶貴意見(jiàn)。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI