Python многопоточность двух клиентов для одновременной работы в течение неопределенного времени с одним сервером - PullRequest
0 голосов
/ 16 апреля 2019

Я пытаюсь выяснить проблему многопоточности, когда два клиента работают вечно и одновременно отправляют запросы на сервер, а сервер постоянно выводит сообщение.

Я посмотрел на многопоточность, когда узналкак один клиент / сервер может отражаться вечно.

Когда я добавил второго клиента, он получил бы последний вывод первого клиента.Затем второй клиент будет неоднократно повторять эхо с сервером, в то время как первый клиент никогда не получает сообщение, замораживая его.

Я застрял на этом в течение нескольких дней, поэтому помощь будет хорошей.

В любом случае,это код, который я использовал для проверки:

ClientA.py

import socket
import time

host = '127.0.0.1' 
port = 2004
BUFFER_SIZE = 2000 

tcpClientA = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
tcpClientA.connect((host, port))

while True:
    data = 'this is client A'
    tcpClientA.send(data)
    data2 = tcpClientA.recv(BUFFER_SIZE)
    print " Client A received data:", data2

Clientb.py совпадает с клиентом A,но с ab

Server.py

import socket
import time
import thread

from threading import Thread 
from SocketServer import ThreadingMixIn 


BUFFER_SIZE = 1024

TCP_IP = '127.0.0.1' 
TCP_PORT = 2004
tcpServer = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
tcpServer.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 

threads = []

def client(ip,port):
    while True:
        data = conn.recv(2048)
        conn.send(data)
    conn.close()

print "Server waiting"
tcpServer.bind((TCP_IP, TCP_PORT))
tcpServer.listen(4)
while True:
    conn,addr=tcpServer.accept()
    thread.start_new_thread(client,(conn,addr))
tcpServer.close()

Ответы [ 2 ]

0 голосов
/ 16 апреля 2019

Ваша исходная функция client использует не переданное соединение, а глобальную переменную conn, которая перезаписывается при каждом соединении.ip - это соединение, переданное client.

Поскольку ваш серверный код импортирует SocketServer, используйте его и упростите код.Этот код создаст поток для каждого клиентского соединения.self.request это розетка подключения:

#!python2
import SocketServer

class Handler(SocketServer.StreamRequestHandler):
    def handle(self):
        while True:
            data = self.request.recv(2048)
            if not data: break
            self.request.sendall(data)

server = SocketServer.ThreadingTCPServer(('',2004),Handler)
server.serve_forever()
0 голосов
/ 16 апреля 2019

Потоки вашего обработчика клиента используют сокет в переменной conn, которая назначена в основном потоке для получения данных и отправки данных.По сути, вы всегда используете только последнее созданное соединение.
Это часто становится видимым в выводе второго клиента сразу после его запуска:

Client B received data: this is client A

С этого момента оба потока-обработчика клиентаобслуживать клиента B только потому, что эта часть вашей client функции ...

    data = conn.recv(2048)
    conn.send(data)

... использует этот conn (сокет) из основного потока, который перезаписывается каждый раз, когда новый клиентподключается к серверу:

conn, addr = tcpServer.accept()

Клиент A ожидает данные с сервера в этот момент:

data2 = tcpClientA.recv(BUFFER_SIZE)

Но поскольку оба потока обработчика клиента на вашем сервере только слушают и записывают всокет, созданный при подключении клиента B, процесс клиента A больше не получает данные и блокирует их на неопределенный срок.

Вы уже передали соответствующее соединение своим потокам обработчика клиента ...

thread.start_new_thread(client, (conn, addr))

... вам просто нужно его использовать:

def client(ip,port):
    while True:
        data = ip.recv(2048)  # receive from ip
        ip.send(data)         # send to ip
    conn.close()
...