通过Python中的套接字传输文本文件

时间:2013-12-13 06:58:39

标签: python sockets

我在PYTHON有一个项目是两台机器(A,B), 1)请求机器A向B发送请求以列出目录(在我的代码中我将其设置为当前目录) 2)在第二个请求机器A中想要下载目录的文本文件。 (将文本文件放在机器B的目录中) 3)在该机器A之后更改文本文件并发送回机器B. 4)并在结束机器A发送两个号码和机器B发回它的结果。 它一直工作到第2步,但之后没有任何事情发生它就像一个真实的我无法理解为什么?! 这是我的代码 机器A(客户):

# -*- coding: UTF-8 -*-
import os
import socket
PORT = 9000
HOST = 'localhost'
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.connect((HOST, PORT))
store=[]
direc = raw_input("Enter The Directory to List : ")
socket.sendall(direc)
len_data = socket.recv(2048)
print int(len_data)
for i in range(int(len_data)):
    data = socket.recv(2048)
    store.append(data)
print("List of Files:")
for i in store:
    print(i)
txt_file = raw_input("Please Choose a TEXT file :")
if store.count(txt_file) is 0:
    print("There no such a TXT file!!")
else:
    socket.sendall(txt_file)

def write_file(name):
    fname = open(name,'ab')
    while True:
        string = socket.recv(2048)
        if string:
            fname.write(string)
        else:
            fname.write("changed")
            fname.close()
            break
def read_file(name):
    fileToSend = open(name, 'rb')
    while True:
        data = fileToSend.readline()
        if data:
            socket.send(data)
        else:
            fileToSend.close()
            break

write_file(txt_file)
read_file(txt_file)
x = raw_input("Enter The First Num: ")
socket.send(x)
y = raw_input("Enter The Second Num: ")
socket.send(y)
result = socket.recv(1024)
print result
raw_input()
socket.sendall('')
socket.close()
exit()

和机器B(服务器):

import os,sys,socket
PORT = 9000
HOST = 'localhost'
tcpsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = (HOST, PORT)
print >>sys.stderr, 'starting up on %s port %s' % server_address
socket.bind((HOST,PORT))
socket.listen(1)
conn, addr = socket.accept()
directory = conn.recv(2048)
if os.listdir(os.curdir):
    data = os.listdir(os.curdir)
len_data = data.__len__()
print(len_data)
if len_data:
        conn.send(str(len_data))
for i in data:
    if i:
        print >>sys.stderr, 'sending data back to the client'
        conn.send(i)
    else:
        break
txt_file_name = conn.recv(2048)
def write_file(name):
    with open(name,'wb') as fname:
        while True:
            string = conn.recv(2048)
            if string:
                fname.write(string)
            else:
                fname.close()
                break
def read_file(name):
    with open(name, 'rb') as fileToSend:
        while True:
            data = fileToSend.readline()
            if data:
                conn.send(data)
            else:
                fileToSend.close()
                break

def add (x,y):
    return str(x+y)

read_file(txt_file_name)
write_file(txt_file_name)

x = conn.recv(1024)
y = conn.recv(1024)
conn.send(add(x,y))
conn.sendall('')
conn.close()
exit()

1 个答案:

答案 0 :(得分:3)

我对你的问题很着迷,并对此进行了调查。虽然我们可以使用socket解决它。我倾向于HTTP协议有几个原因:

  • 你不必自己动手“握手”。 HTTP协议提供了请求文件,上传文件和进行一些处理(您的步骤#4)
  • 您可以使用网络浏览器测试服务器
  • Web服务现在非常流行。这是了解Web服务的一个小步骤。

这是服务器代码(server.py):

from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
import os

class MyHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        global running
        if self.path == '/':
            self.list_files()
        elif self.path.startswith('/calculation'):
            self.send_calculation()
        elif self.path.startswith('/quit'):
            self.send_response(200)
            running = False
        else:
            self.send_file(self.path[1:])

    def do_POST(self):
        filename = self.path[1:] # Remove the / from the path
        filesize = int(self.headers['Content-Length'])
        contents = self.rfile.read(filesize)

        with open(filename, 'w') as f:
            f.write(contents.decode())

        self.send_response(200)

    def send_file(self, filename):
        # Check to see if file exists and is a file, not directory
        if os.path.isfile(filename):
            self.send_response(200)
            self.send_header('Content-Type', 'text/plain')
            self.end_headers()

            # Read and send the contents of the file
            with open(filename) as f:
                contents = f.read()
            self.wfile.write(contents)
        else:
            self.send_response(404)
            self.send_header('Content-Type', 'text/plain')
            self.end_headers()
            self.wfile.write('Dude! File not found')

    def send_calculation(self):
        empty, operation, number1, number2 = self.path.split('/')
        result = int(number1) + int(number2)
        self.send_response(200)
        self.send_header('Content-Type', 'text/plain')
        self.end_headers()
        self.wfile.write(result)

    def list_files(self):
        file_list = os.listdir(os.curdir)
        if file_list:
            self.send_response(200)
            self.send_header('Content-Type', 'text/plain')
            self.end_headers()
            for filename in file_list:
                self.wfile.write('{}\n'.format(filename))

#
# Main
#
running = True
server = HTTPServer(('', 9000), MyHandler)
print 'Server started on host:{}, port:{}'.format(*server.server_address)
while running:
    server.handle_request()

这是客户端代码(client.py):

import urllib2
import urlparse

def make_url(server, port, path, scheme='http'):
    netloc = '{}:{}'.format(server, port)
    url = urlparse.urlunsplit((scheme, netloc, path, '', ''))
    return url

#
# Main
#
server = '10.0.0.5'
port = 9000

# 1 - Request directory listing
url = make_url(server, port, '/')
file_list = urllib2.urlopen(url).read()
print 'Files from server:'
for filename in file_list.splitlines():
    print '- {}'.format(filename)

# 2 - Request contents of a file
filename = raw_input('Type a file name: ')
url = make_url(server, port, filename)
contents = urllib2.urlopen(url).read()
print 'Contents:'
print contents

# 3 - Upload a file to the server
contents = 'hello, world.\nThe End'
filename = 'foo.txt'
url = make_url(server, port, filename)
f = urllib2.urlopen(url, data=contents)

# 4 - Do some calculation
n1 = 19
n2 = 5
path = '/calculation/{}/{}'.format(n1, n2)
url = make_url(server, port, path)
result = int(urllib2.urlopen(url).read())
print '{} + {} = {}'.format(n1, n2, result)

# Send quit signal

url = make_url(server, port, '/quit')
urllib2.urlopen(url).read()

Web服务

服务器实际上是一个Web服务,它提供以下服务:

获取目录列表

GET http://server:port/

此服务将返回当前目录中的文件列表。

获取文件的内容

GET http://server:port/filename

以纯文本格式返回文件的内容。

上传文件

POST http://server:port/filename

将文件从客户端复制到服务器。如果该文件已存在于服务器上,请覆盖它。

做一些计算

GET http://server:port/calculation/x/y

返回x + y

关闭服务器

GET http://server:port/quit

告诉服务器退出。

错误处理

为了简洁和清晰起见,我没有添加错误处理代码。以下是我能想到的一些错误情况:

  • 检索不存在的文件或目录(服务器)
  • 由于缺少文件写入权限(服务器)而导致上传失败
  • 在计算服务中,参数不是数字(服务器)
  • 服务器未启动,端口错误,服务器(客户端)错误

其他讨论

  • 一般来说,GET意味着数据从服务器流向客户端,而POST则反方向。
  • 要从服务器测试GET操作,您可以使用浏览器。例如,要从192.168.1.5(端口9000)检索目录内容,请将Web浏览器指向:

    http://192.168.1.5:900/  
    
  • 测试POST比较棘手,请参阅上传部分中的客户端代码,了解使用POST的方法。

  • 在服务器代码中,do_GET()函数处理所有GET请求,do_POST()函数处理所有POST请求。