簡體   English   中英

python套接字文件傳輸

[英]python socket file transfer

我正在嘗試通過套接字寫入傳輸文件或數據塊。 我覺得好像我正在重新發明輪子,但我對一個簡單的解決方案的搜索失敗了(我發現的一切都太簡單或太復雜)。 服務器將在運行python 2.5.4的手機上運行。 預期的應用是在電話和主機之間同步音樂文件。

這是我所擁有的內容,似乎有效。 我發送並收到“確定”以分解流。

是來回發送'ok'作為停止位來分解數據流是一種合理的技術嗎?

有沒有標准的方法來做到這一點?

考慮到手機內存和處理能力的限制,在手機上運行任何類型的庫服務器(ftp,http)都不是一個有用的解決方案。

服務器:

import socket

c = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
c.bind(('', 1234))
c.listen(1)
s,a = c.accept()

while True:
    data = s.recv(1024)
    cmd = data[:data.find('\n')]

    if cmd == 'get':
        x, file_name, x = data.split('\n', 2)
        s.sendall('ok')
        with open(file_name, 'rb') as f:
            data = f.read()
        s.sendall('%16d' % len(data))
        s.sendall(data)
        s.recv(2)

    if cmd == 'end':
        s.close()
        c.close()
        break

客戶:

import socket

s = socket.socket()
s.connect(('192.168.1.2', 1234))

def get_file(s, file_name):
    cmd = 'get\n%s\n' % (file_name)
    s.sendall(cmd)
    r = s.recv(2)
    size = int(s.recv(16))
    recvd = ''
    while size > len(recvd):
        data = s.recv(1024)
        if not data: 
            break
        recvd += data
    s.sendall('ok')
    return recvd

print get_file(s, 'file1')
print get_file(s, 'file2')
s.sendall('end\n')

是來回發送'ok'作為停止位來分解數據流是一種合理的技術嗎?

大多數協議使用一些終結器或另一個。 流行的替代方案是'\\ r \\ n','\\ r \\ n \\ r \\ n'或EOF(ctrl + d),但這些只是任意選擇,並且沒有比你的'ok'更差或更好,只要你的客戶和服務器知道如何處理它。

你的代碼看起來不錯。

您實際上不需要跨文件大小發送。 您可以使用while True ,因為檢查if not data: break將停止循環。

while True:
    data = s.recv(1024)

    if not data: print " Done "; break

    recvd += data

另外,為什么你發送'ok'是對方不檢查它? 你只是在每邊跳過2個字節。

你不需要迎合多個客戶嗎? 不需要多線程?

你可以看看這個實現。 它還負責文件是否在子目錄中。 這是鏈接

服務器

import socket
import os

print('Waiting for clinet to connect...')
c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
c.bind(('', 1234))
c.listen(1)
s, a = c.accept()

print('Connected. Going to receive file.')
s.sendall('getfilename')
filename = s.recv(1024)
if '/' in filename:
    dir = os.path.dirname(filename)
    try:
        os.stat(dir)
    except:
        print('Directory does not exist. Creating directory.')
        os.mkdir(dir)
f = open(filename, 'wb')
print('Filename: ' + filename)

while True:
    s.sendall('getfile')
    size = int(s.recv(16))
    print('Total size: ' + str(size))
    recvd = ''
    while size > len(recvd):
        data = s.recv(1024)
        if not data: 
            break
        recvd += data
        f.write(data)
        #print(len(recvd))
    break
s.sendall('end')
print('File received.')

s.close()
c.close()
f.close()

客戶

import socket
import sys

if len(sys.argv) > 1 :
    print('Trying to connect...')
    s = socket.socket()
    s.connect(('127.0.0.1', 1234))

    print('Connected. Wating for command.')
    while True:
        cmd = s.recv(32)

        if cmd == 'getfilename':
            print('"getfilename" command received.')
            s.sendall(sys.argv[1])

        if cmd == 'getfile':
            print('"getfile" command received. Going to send file.')
            with open(sys.argv[1], 'rb') as f:
                data = f.read()
            s.sendall('%16d' % len(data))
            s.sendall(data)
            print('File transmission done.')

        if cmd == 'end':
            print('"end" command received. Teminate.')
            break

有沒有標准的方法來做到這一點?

是。 http://www.faqs.org/rfcs/rfc959.html

描述執行此操作的標准方法。

這是一個實現: http//docs.python.org/library/ftplib.html

rsync是在兩台計算機之間同步文件的標准方法。 你可以用這樣的http://code.activestate.com/recipes/577518-rsync-algorithm/在Python中編寫它,或者你可以像這樣http://freshmeat.net/projects/pysync/包裝C庫並進行一些調整比如用MD5替換MD4。

或者,如果你想在套接字級別這樣做,你真的應該使用asyncore asynchat。 這是一個用asynchat http://pyftpdlib.googlecode.com/svn-history/r20/trunk/pyftpdlib/FTPServer.py編寫的FTP服務器,但你應該先閱讀http://www.doughellmann.com/PyMOTW/asynchat /注意關於消息終結者點2的部分。許多網絡協議都做這樣的奇怪的事情,即有時他們發送和接收全行命令和響應,有時他們發送和接收任意數據的塊,前面是計數塊中有多少字節。 使用asynchat可以更輕松地處理這個問題,並且您的程序也可以更好地擴展。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM