作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在学习套接字编程和 python。我需要创建一个服务器来接受来自客户端的命令并将一个大文本文件发送回客户端。客户端然后将完整的文本文件保存到它的目录中。在我的代码中,服务器逐行发送整个文本文件,但客户端只能接受 1024 字节。我不确定我需要添加什么,以便客户端可以从服务器接收整个文本文件并将其保存到它的目录中。有人可以看看我的代码并指出正确的方向吗?非常感谢您的帮助。
服务器.py
import socket
import sys
import os
from thread import *
HOST = ''
PORT = 8888
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created'
try:
server_socket.bind((HOST, PORT)) #bind to a address(and port)
except socket.error, msg:
print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
sys.exit()
print 'Socket bind complete'
#put the socket in listening mode
server_socket.listen(10) #maximum 10 connections
print 'TCP Server Waiting for client on port 30021'
#wait to accept a connection - blocking call
client, addr = server_socket.accept()
#display client information
print 'Connected with ' + addr[0] + ':' + str(addr[1])
try:
#keep talking with the client
while 1:
#Receiving from client
data = client.recv(1024)
#command: list
commandlist = data.split()
if (commandlist[0].strip() in ('list')):
reply = 'Directory: ' + os.getcwd() #current directory
client.send(reply)
elif (commandlist[0] == 'get' and len(commandlist) >= 2):
filename = commandlist[1]
reply = filename
#validate filename
if os.path.exists(filename):
length = os.path.getsize(filename)
with open(filename, 'r') as infile:
for line in infile:
reply = line
client.sendall(reply)
#f = open(filename, 'r')
#reply = f.read()
#client.send(piece)
#f.close()
else:
reply = 'File not found'
client.send(reply)
elif (commandlist[0] == 'get' and len(commandlist) < 2):
#if the command argument is less than 2
reply = 'Provide a filename please'
client.send(reply)
else:
reply = 'Error: Wrong command'
client.send(reply)
except KeyboardInterrupt:
print "Exiting gracefully."
finally:
server_socket.close()
客户端.py
#Socket clicent in python
import socket #for sockets
import sys #for exit
command = ' '
socksize = 1024
#return a socket descriptor which can be used in other socket related functions
#properties: address family: AF_INET (IP v4)
#properties: type: SOCK_STREAM (connection oriented TCP protocol)
try:
#create an AF_INET, STREAM socket (TCP)
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, msg: #error handling
print 'Failed to create socket. Error code: ' + str(msg[0]) + ', Error message: ' + msg[1]
sys.exit();
print 'Socket Created'
#Get the IP address of the remote host/url
#connect to IP on a certain 'port' using the connect
host = '' #symbolic name meaning the local host
port = 8888 #arbitrary non-privileged port
try:
remote_ip = socket.gethostbyname(host)
except socket.gaierror:
#could not resolve
print 'Hostname could not be resolved. Existing'
sys.exit()
print 'IP address of ' + host + ' is ' + remote_ip
#Connect to remote server
client_socket.connect((remote_ip, port))
print 'Socket Connected to ' + host + ' on ip ' + remote_ip
buf = ''
#Send some data to remote server
while True:
print 'Enter a command: list or get <filename>'
command = raw_input()
if command.strip() == 'quit':
break
client_socket.send(command)
data = client_socket.recv(socksize)
print data
#Close the socket
client_socket.close()
最佳答案
问题是客户端必须从一开始就知道文件的大小,否则它将不知道要读取多少数据。已经有协议(protocol)(如 HTTP)可以为您处理它,但您可以自己实现它。像这样:
server.py
if os.path.exists(filename):
length = os.path.getsize(filename)
client.send(convert_to_bytes(length)) # has to be 4 bytes
with open(filename, 'r') as infile:
d = infile.read(1024)
while d:
client.send(d)
d = infile.read(1024)
客户端.py
client_socket.send(command)
if command.strip().startswith("get"):
size = client_socket.recv(4) # assuming that the size won't be bigger then 1GB
size = bytes_to_number(size)
current_size = 0
buffer = b""
while current_size < size:
data = client_socket.recv(socksize)
if not data:
break
if len(data) + current_size > size:
data = data[:size-current_size] # trim additional data
buffer += data
# you can stream here to disk
current_size += len(data)
# you have entire file in memory
请注意,这只是一个想法,其中涉及很多问题。
当然你必须实现convert_to_bytes
(它总是必须返回4字节(或其他固定数字)否则协议(protocol)将被破坏,必要时添加零)和 bytes_to_number
函数。
此类实现的示例:
def convert_to_bytes(no):
result = bytearray()
result.append(no & 255)
for i in range(3):
no = no >> 8
result.append(no & 255)
return result
def bytes_to_number(b):
# if Python2.x
# b = map(ord, b)
res = 0
for i in range(4):
res += b[i] << (i*8)
return res
关于python - 如何在 python 中进行大文本文件传输?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20007319/
我是一名优秀的程序员,十分优秀!