无法在Python套接字编程中分离文件名和文件内容

0 投票
2 回答
1165 浏览
提问于 2025-04-17 19:23

我正在尝试通过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:]

撰写回答