我正在尝试实现一个程序,该程序使用TCP套接字同时从客户端向服务器发送文件。我有一个客户端和服务器代码,当并发数为1时可以正常工作,但是当并发数为2或更高时无法正确传输。
buffer.py
class Buffer:
def __init__(self,s):
'''Buffer a pre-created socket.
'''
self.sock = s
self.buffer = b''
def get_bytes(self,n):
'''Read exactly n bytes from the buffered socket.
Return remaining buffer if <n bytes remain and socket closes.
'''
while len(self.buffer) < n:
data = self.sock.recv(1024)
if not data:
data = self.buffer
self.buffer = b''
return data
self.buffer += data
# split off the message bytes from the buffer.
data,self.buffer = self.buffer[:n],self.buffer[n:]
return data
def put_bytes(self,data):
self.sock.sendall(data)
def get_utf8(self):
'''Read a null-terminated UTF8 data string and decode it.
Return an empty string if the socket closes before receiving a null.
'''
while b'\x00' not in self.buffer:
data = self.sock.recv(1024)
if not data:
return ''
self.buffer += data
# split off the string from the buffer.
data,_,self.buffer = self.buffer.partition(b'\x00')
return data.decode()
def put_utf8(self,s):
if '\x00' in s:
raise ValueError('string contains delimiter(null)')
self.sock.sendall(s.encode() + b'\x00')
client.py
import socket
import threading
import os
from concurrent.futures import ThreadPoolExecutor, as_completed
import buffer
HOST = '127.0.0.1'
PORT = 2345
def main():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
sbuf = buffer.Buffer(s)
files_to_send = ['text.txt', 'some.txt']
with ThreadPoolExecutor(max_workers=1) as executor:
futures = [executor.submit(_send_file, sbuf, file_name) for file_name in files_to_send]
for future in as_completed(futures):
result = future.result()
print result
def _send_file(sbuf, file_name):
print(file_name)
sbuf.put_utf8(file_name)
file_size = os.path.getsize(file_name)
sbuf.put_utf8(str(file_size))
with open(file_name, 'rb') as f:
sbuf.put_bytes(f.read())
print('File Sent')
if __name__ == '__main__':
main()
server.py
import socket
import os
import buffer
HOST = ''
PORT = 2345
try:
os.mkdir('uploads')
except:
pass
s = socket.socket()
s.bind((HOST, PORT))
s.listen(10)
print("Waiting for a connection.....")
while True:
conn, addr = s.accept()
print("Got a connection from ", addr)
connbuf = buffer.Buffer(conn)
while True:
file_name = connbuf.get_utf8()
if not file_name:
break
file_name = os.path.join('uploads',file_name)
print('file name: ', file_name)
file_size = int(connbuf.get_utf8())
print('file size: ', file_size )
with open(file_name, 'wb') as f:
remaining = file_size
while remaining:
chunk_size = 4096 if remaining >= 4096 else remaining
chunk = connbuf.get_bytes(chunk_size)
if not chunk: break
f.write(chunk)
remaining -= len(chunk)
if remaining:
print('File incomplete. Missing',remaining,'bytes.')
else:
print('File received successfully.')
print('Connection closed.')
conn.close()
以上代码在并发max_workers为1时有效,但在增加worker数时失败。我猜想这与服务器端的并发有关,但是我不知道在何处确切地并发。要实现并发文件传输,该代码需要做什么/更改?