Я сделал файловый сервер на Python, используя сокеты и потоки.Программа должна позволять клиенту загружать и скачивать файлы с сервера.
Программа работает отлично, когда работает только один поток, но когда работают оба потока, сервер выдает ошибку при попытке загрузить файл, а при попытке загрузить программу просто перестает делать что-либо после входа клиента'Y', чтобы начать загрузку.
Вот код для клиента:
import socket
import os
def DownloadFile(s, host, port):
s.connect((host, port))
s.send(str.encode('DNLD'))
filename = input('Filename? ->')
if filename != 'q':
s.send(str.encode(filename))
data = s.recv(2048).decode('UTF-8')
if data[:6] == 'EXISTS':
filesize = data[6:]
message = input('File Exists, ' + str(filesize) + ' Bytes. Download? (Y/N) ->')
if message == 'Y' or message == 'y':
s.send(str.encode('OK'))
f = open('copy of '+filename, 'wb')
data = s.recv(2048)
totalRecv = len(data)
f.write(data)
while totalRecv < int(filesize):
data = s.recv(2048)
totalRecv += len(data)
f.write(data)
print('{}'.format(round((totalRecv/float(filesize))*100),2)+'% Complete')
print('Download Complete!')
s.close()
else:
print('File does not exist')
s.close()
Main()
def UploadFile(s, host, port):
s.connect((host, port))
s.send(str.encode('UPLD'))
filename = input('Filename? ->')
if os.path.isfile(filename):
filesize = os.path.getsize(filename)
filesize = str(filesize)
s.send(str.encode('EXISTS ' + filename))
s.send(str.encode(filesize))
ready = input('Ready to upload. Proceed? (Y/N) ->')
if ready == 'Y' or ready == 'y':
s.send(str.encode('OK'))
with open(filename, 'rb') as f:
bytesToSend = f.read(2048)
s.send(bytesToSend)
while bytesToSend != '':
bytesToSend = f.read(2048)
s.send(bytesToSend)
s.close()
else:
print('File does not exist.')
s.close()
Main()
def Main():
host = '127.0.0.1'
port = 10000
s = socket.socket()
while True:
choice = int(input('Please enter your choice:\n\n1. Upload a file to the server.\n2. Download a file from the server\n3. Quit.\n\n->'))
if choice == 1:
UploadFile(s, host, port)
break
elif choice == 2:
DownloadFile(s, host, port)
break
elif choice == 3:
s.close()
break
else:
print('Please enter a valid choice.')
if __name__ == '__main__':
Main()
А вот код для сервера:
import socket
import threading
import os
def SendFile(name, s):
check = s.recv(2048).decode('UTF-8')
if check == 'DNLD':
filename = s.recv(2048)
if os.path.isfile(filename):
send = os.path.getsize(filename)
send = str(send)
s.send(str.encode('EXISTS ' + send))
userResponse = s.recv(2048)
userResponse = userResponse.decode('UTF-8')
if userResponse[:2] == 'OK':
with open(filename, 'rb') as f:
bytesToSend = f.read(2048)
s.send(bytesToSend)
while bytesToSend != '':
bytesToSend = f.read(2048)
s.send(bytesToSend)
else:
s.send(str.encode('ERR'))
s.close()
def ReceiveFile(name, s):
check = s.recv(2048).decode('UTF-8')
if check == 'UPLD':
data = s.recv(2048).decode('UTF-8')
if data[:6] == 'EXISTS':
filename = data[6:]
data = s.recv(2048).decode('UTF-8')
filesize = data
userResponse = s.recv(2048)
userResponse = userResponse.decode('UTF-8')
if userResponse[:2] == 'OK':
f = open('copy of '+filename, 'wb')
data = s.recv(2048)
totalRecv = len(data)
f.write(data)
while totalRecv < int(filesize):
data = s.recv(2048)
totalRecv += len(data)
f.write(data)
print('Download Complete!')
def Main():
host = '127.0.0.1'
port = 10000
s = socket.socket()
s.bind((host, port))
s.listen(5)
print('Server Started')
while True:
c, addr = s.accept()
print('Client Connected: ' + str(addr))
Send = threading.Thread(target=SendFile, args=('sendThread', c))
Send.start()
Receive = threading.Thread(target=ReceiveFile, args=('retrThread', c))
Receive.start()
s.close()
if __name__ == '__main__':
Main()
ЕслиЯ должен был закомментировать Send.start () или Receive.start (), тогда любой закомментированный поток будет работать отлично.
Вот ошибка, сообщаемая на сервере при попытке загрузить файл с обоимиРаботающие потоки:
Exception in thread Thread-2:
Traceback (most recent call last):
File "C:\Python34\lib\threading.py", line 920, in _bootstrap_inner
self.run()
File "C:\Python34\lib\threading.py", line 868, in run
self._target(*self._args, **self._kwargs)
File "(file location)", line 28, in ReceiveFile
check = s.recv(2048).decode('UTF-8')
OSError: [WinError 10038] An operation was attempted on something that is not a socket
И вот вывод в клиенте при попытке загрузить файл, когда работают оба потока:
Please enter your choice:
1. Upload a file to the server.
2. Download a file from the server
3. Quit.
->2
Filename? ->cat.jpg
File Exists, 10634 Bytes. Download? (Y/N) ->Y
После ввода Y ничего больше не происходит.
Если кто-нибудь знает, что происходит не так, я был бы очень признателен за помощь.