Как сформировать новое соединение сокета с многопоточностью в PythonPython

Программы на Python
Ответить
Anonymous
 Как сформировать новое соединение сокета с многопоточностью в Python

Сообщение Anonymous »

Проект, над которым я работаю, представляет собой симуляцию/макет службы VPN. Я понял, как подключить несколько клиентов к одному серверу, используя циклы и многопоточность, но теперь я изо всех сил пытаюсь понять, как выборочная передача информации между этими потоками поддерживает каждое соединение. Процесс, как я себе представлял, таков.
  • Запустите сервер и прослушивайте входящие соединения
  • запустите других клиентов, позвольте им подключиться к серверу
  • Когда пользовательский клиент подключается, сервер должен обнаружить его и запустить пользовательский поток
  • Клиент пользователя должен отправить данные на сервер, сообщая ему, к какому клиенту подключиться
  • Затем сервер должен начать туннелирование информации между клиентом пользователя и выбранным клиентом
Проблема в том, что из-за того, как работает цикл для подключения всех клиентов, у меня нет способа выбрать, какие соединения остаются открытыми или через какие из них туннелировать информацию. Все соединения создаются одновременно под одним и тем же именем и вызывают одну и ту же функцию для выполнения своих процессов. Вот код, на основе которого я работаю.

Код: Выделить всё

def handle_client(conn, addr):
print(f"Connection established with {addr}.")

while True:
try:
data = conn.recv(1024)  # Receive data from the client
if not data:
break  # Terminate the connection if no data is received
print(f"Received from {addr}: {data.decode()}")
conn.sendall(f"Server response: {data.decode()}".encode())  # Send the received data back to the client
except ConnectionResetError:
print(f"Client {addr} has disconnected.")
break
conn.close()
print(f"Connection with {addr} closed.")# Start the server

def start_server():
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket:
server_socket.bind((HOST, PORT))
server_socket.listen()
print(f"Server listening on {HOST}:{PORT}...")

while True:
conn, addr = server_socket.accept()  # Accept a client connection
thread = threading.Thread(target=handle_client, args=(conn, addr))
thread.start()  # Start a new thread for each client
print(f"Active connections: {threading.activeCount() - 1}")

if __name__ == "__main__":
start_server()
А вот модифицированный код, который я написал. Моя мысль заключалась в том, чтобы покончить с циклом while-True и поддерживать только избранное, ограниченное количество других клиентских соединений, к которым можно было бы обращаться по имени для простоты доступа. Я также добавил специальную функцию для обслуживания соединения Пользователь-Клиент, которая будет вызываться при обнаружении соответствующего IP-адреса. Наконец, я добавил очередь для туннелирования информации между пользователем и выбранным Клиентом.

Код: Выделить всё

##Code to handle user cLient
def handle_user(conn, addr,in_q):
print(f"Connection established with {addr}.")
while True:
try:
data = conn.recv(1024).decode()  # Receive data from the client
if not data:
break  # Terminate the connection if no data is received
in_q.put(data)
time.sleep(3)
toClient = in_q.get()
conn.sendall({data.encode()})
except ConnectionResetError:
print(f"Client {addr} has disconnected.")
break
conn.close()
print(f"Connection with {addr} closed.")# Start the server

#code to handle other clients
def handle_client(conn,addr):
print(f"Connection established with {addr}.")
while True:
try:
conn.sendall()
data = conn.recv(1024)  # Receive data from the client
if not data:
break  # Terminate the connection if no data is received
print(f"Received from {addr}: {data.decode()}")
conn.sendall(f"Server response: {data.decode()}".encode())  # Send the received data back to the client
except ConnectionResetError:
print(f"Client {addr} has disconnected.")
break
conn.close()

def start_server():
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket:
server_socket.bind((HOST, PORT))
server_socket.listen()
print(f"Server listening on {HOST}:{PORT}...")

q = Queue() #create a new queue
while True:
conn, addr = server_socket.accept()  # Accept a client connection
if addr == '10.9.0.2':
User_thread = threading.Thread(target=handle_user, args=(conn, addr,q))
User_thread.start()  # Start thread to handle User
conn.sendall(f"Which server would you like to connect to?\n0)to termiante connection\n1)UK\n2)Nowray\n3)Egypt")
data = conn.recv(1024).decode()  # Receive data from the client
if data == 1:
t1.start()
elif data == 2:
t2.start()
elif data == 3:
t3.start()
elif addr == '10.9.0.3':
t1 = threading.Thread(target=handle_client, args=(conn, addr,q))
# Start a new thread for each client
elif addr == '10.9.0.4':
t2 = threading.Thread(target=handle_client, args=(conn, addr,q))
t2.start()  # Start a new thread for each client
elif addr == '10.9.0.5':
t3 = threading.Thread(target=handle_client, args=(conn, addr,q))
t3.start()  # Start a new thread for each client
print(f"Active connections: {threading.activeCount() - 1}")

if __name__ == "__main__":
start_server()
Как видите, это беспорядок. Моей первой мыслью было заставить поток handle-user поговорить с пользователем и получить от него выбор, к какому другому клиенту они хотели бы подключиться. Но это провалилось, когда я понял, что не существует чистого способа вернуть эту информацию в Main, не завершая этот поток и не закрывая соединение с пользователем. Поэтому я попытался переместить этот процесс в саму функцию Main и запустить другие потоки на основе соединения пользователя, но теперь я не уверен, что старый conn, переданный клиентским потокам, будет перезаписан циклом, если потоки запускаются только на той итерации, где подключается пользователь.
TLDR: мне нужен способ выбирать, с какими потоками я работаю в любой момент времени, на основе входных данных из пользовательского потока

Подробнее здесь: https://stackoverflow.com/questions/798 ... -in-python
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»