无法在Python套接字编程中分离文件名和文件内容
我正在尝试通过TCP套接字编程,把数据从客户端发送到服务器端。
我做的事情是读取客户端目录中的文件名,然后通过发送clientSocket.send("FILE "+fileToTransfer + "\n")
把文件名发送到服务器端。然后在服务器端,我用正则表达式来提取文件名。
但是,客户端总是会把"FILE fileName.txt"和文件内容一起发送过来。所以我想在服务器端需要用正则表达式来分开文件名和文件内容。
所以我在服务器端做的是用getFileName = re.match(r'FILE (.*)(\n)(.*)',data)
来分别获取文件名和文件内容。不幸的是,(.*)
不包括换行符。
在这种情况下,我该如何分开文件内容和文件名呢?有没有办法让客户端先发送文件名,然后等服务器端接收到文件名后再发送文件内容?或者有没有正则表达式可以用来分开文件名和文件内容?
2 个回答
1
如果你只是想修正正则表达式,可以把这一行改成:
getFileName = re.match(r'FILE (.*?)(\n)(.*)', data, re.DOTALL)
这里的 DOTALL
标志让 .
也能匹配换行符。额外加上的 ?
让 *
这个符号变得不贪心,也就是说,它会在遇到第一个换行符时就停止(我假设换行符不可能是文件名的一部分)。
你可能更应该做的是把文件名作为头信息的一部分发送过去。
2
你可以把文件大小和文件名一起发送给服务器。这样服务器就知道应该读取多少字节的数据。这样的话,你就不需要把整个文件的内容都加载到内存里,而是可以分块读取,直到文件的大小读取完毕(也就是变成零),然后把这些块写入磁盘。可以像这样操作:
## client side
# get file size here, for example:
# filesize = os.path.getfilesize(filepath)
sock.sendall("FILE %s %d\n" % (filename, filesize))
sock.sendall(fd.read())
...
## server side
# error handling is left out
header = ""
while True:
d = sock.recv(1)
if d == '\n':
break
header += d
filesize = int(header.split()[-1])
# or search for the last space in header
# and get a substring of header as filename
filename = "".join(header.split()[1:-1])
data = ""
while filesize > 0:
chunk = sock.recv(1024) # or any amount of data
filesize -= chunk
data += chunk
或者,你也可以放弃使用正则表达式,直接找到第一个 \n
:
## client side
sock.sendall("FILE %s\n")
sock.sendall(fd.read())
...
## server side
# data = read data here
newline = data.find('\n')
assert newline != -1 # some error handling here
header = data[newline]
filename = header[len("FILE "):]
content = data[newline+1:]