Как сделать анонимную отправку очков в python?
Пытаюсь реализовать анонимный перевод из одного счета в другой. В план, который я придумал, чтобы добиться анонимности.:
План:
Создать две переменные
balanceиanonim.Инициализировать переменную
balanceдля хранения очков.Если клиент хочет перевести другу свои очки, то:
◦Разделить его сумму очков(которое он отправил) на два рандомнох числа.
◦Передать каждое полученное число двум случайным клиентам в переменную
anonim.Повторить данный шаг 3 раза:
◦Взять у клиентов, которые получили очки, разделить их очки на два случайных числа и отправить другим двум случайным клиентам в переменную "anonim".
Просуммировать значения в переменной
anonimвсех конечных случайных клиентов.Отправить полученную сумму на счет друга.
Кратко:
- Алгоритм оперирует по следующей схеме: сумма перевода разбивается на два случайных числа и направляется на скрытые счета двух случайно выбранных пользователей. Процедура повторяется дважды для усиления анонимности. В итоге, суммы передаются получателям в случайном порядке, что обеспечивает дополнительный уровень конфиденциальности.
Вот рисунок, как это должно все выглядит:
Проблемы:
Главным вызовом, с которым я столкнулся, является неспособность эффективно реализовать концепцию на сервере. При работе с сервером возникают проблемы — либо он перестает отвечать, либо выводит ошибку и перестает функционировать. В теории, алгоритм должен брать случайных клиентов из переменной clients = {} и включать их в процесс. Однако, как я уже упоминал, возникают ошибки или просто отсутствует ответ от сервера.
Вот примерно, что я пытаюсь получить:
import random
x = int(input("Введите сумму очков, которую хотите перевести другу: "))
while True:
anonim1 = random.randint(1, x)
anonim2 = random.randint(1, x)
anonim3 = random.randint(1, anonim1)
anonim4 = random.randint(1, anonim1)
anonim5 = random.randint(1, anonim2)
anonim6 = random.randint(1, anonim2)
if anonim1 + anonim2 == x and anonim3 + anonim4 + anonim5 + anonim6 == x:
break
print(f"Значение переменной anonim у первого клиента: {anonim1}")
print(f"Значение переменной anonim у второго клиента: {anonim2}")
print(f"Из переменной anonim у первого клиента: {anonim1}, появилось {anonim3} и {anonim4} и отправилось другим клиентам")
print(f"Из переменной anonim у второго клиента: {anonim2}, появилось {anonim5} и {anonim6} и отправилось другим клиентам")
balancefreand = anonim3 + anonim4 + anonim5 + anonim6
print(f"Баланс друга теперь: {balancefreand}")
(Данный код никак не связан не с сервером, не с клиентом. Я тут просто показал, как должна выглядеть моя задумка)
Вот пример, как это должно выглядеть по моей задумки:
Пользователь вводит команду для перевода очков:
Обмен очков: загрузка данных на сервер:
Буду очень признателен за помощь в реализации моей идеи и оптимизации программы. Внизу привожу свой код, в котором еще нет функционала анонимных переводов, так как мне не совсем ясен лучший способ воплотить мою задумку. Заранее благодарю всех, кто окажет мне помощь в этом вопросе!
Изменение кода сервера и клиента:
После тщательного обдумывания советов, я принял решение полностью переделать свой код, внедрив механизм буферизации для оптимизации работы. Несмотря на то, что не все прошло гладко, прошу вас смотреть на это снисходительно. Вместо стандартных модулей socket и threading, я воспользовался возможностями модуля asyncio. Я надеюсь, что все выполнено правильно, но буду благодарен за любые замечания и советы, высказанные в комментариях.
Сервер и клиент:
Сервер:
import asyncio
import random
connected_users = {}
user_balances = {}
async def handle_client(reader, writer):
user_id = random.randint(100000, 999999)
connected_users[user_id] = writer
user_balances[user_id] = 100
writer.write(str(user_id).encode())
print(f"Пользователь с айди {user_id} и балансом 100 подключился. Онлайн: {len(connected_users)}")
try:
while True:
data = await reader.read(100)
message = data.decode().strip()
if message.startswith('/trade '):
parts = message.split()
if len(parts) == 3:
trade_id = int(parts[1])
amount = int(parts[2])
if trade_id in connected_users and amount <= user_balances[user_id]:
user_balances[user_id] -= amount
user_balances[trade_id] += amount
writer.write(f"Успешно обменено {amount} очков с пользователем {trade_id}\n".encode())
connected_users[trade_id].write(f"Получено {amount} очков от пользователя {user_id}\n".encode())
else:
writer.write("Ошибка при обмене\n".encode())
elif message == '/balance':
writer.write(f"Ваш текущий баланс: {user_balances[user_id]} очков\n".encode())
elif message == '/help':
writer.write("Доступные команды:\n/trade [айди] [сумма] - выполнить обмен очков\n/balance - проверить баланс\n/help - отобразить все доступные команды и инструкцию для команды /trade\n/exit - выйти из сервера\n".encode())
elif message == '/exit':
writer.write("До свидания! Соединение будет закрыто\n".encode())
break
await asyncio.sleep(0.1)
except asyncio.CancelledError:
pass
finally:
del connected_users[user_id]
del user_balances[user_id]
print(f"Пользователь с айди {user_id} отключился. Онлайн: {len(connected_users)}")
writer.close()
async def main():
server = await asyncio.start_server(
handle_client, '127.0.0.1', 8888)
addr = server.sockets[0].getsockname()
print(f'Server started on {addr}')
async with server:
await server.serve_forever()
asyncio.run(main())
Клиент:
import asyncio
async def handle_client(reader, writer):
data = await reader.read(100)
user_id = int(data.decode())
print(f"Вы получили айди: {user_id}")
async def receive_messages():
while True:
data = await reader.read(100)
if not data:
break
print(data.decode(), end='')
task = asyncio.create_task(receive_messages())
try:
while True:
command = input("Введите команду: ")
if command.lower() == '/exit':
writer.write('/exit'.encode())
await writer.drain()
break
elif command.lower() == '/balance':
writer.write('/balance'.encode())
await writer.drain()
response_data = await reader.read(1024)
print(response_data.decode())
elif command == '/help':
writer.write('/help'.encode())
await writer.drain()
response_data = await reader.read(1024)
print("Доступные команды:\n", response_data.decode())
elif command.startswith('/trade'):
recipient_id, amount = command.split()[1:]
trade_command = f"/trade {recipient_id} {amount}"
writer.write(trade_command.encode())
await writer.drain()
response_data = await reader.read(1024)
print(response_data.decode())
else:
print("Неверная команда")
except asyncio.CancelledError:
pass
finally:
task.cancel()
writer.close()
await writer.wait_closed()
async def main():
reader, writer = await asyncio.open_connection('127.0.0.1', 8888)
await writer.drain() # Отправляем пустое сообщение для получения айди
await handle_client(reader, writer)
asyncio.run(main())
Ответы (1 шт):
Прочитал ваш код, заметил несколько проблем:
- Id может стать не уникальным (
id_value = str(random.randint(100000, 999999))), поэтому стоит проверить, еслиid_value in clients.keys(); - Где команда "/balance", вы отправляете текст "Ваши очки: ..." с сервера, а клиент подставляет этот ответ. В итоге получится: "Ваши очки: Ваши очки: ...";
- Не совсем проблема конечно, но можно прямо на клиенте развернуть команду "/help"; Это всё что я заметил на данный момент.


