2017-11-08 3 views
0

많은 클라이언트의 연결을 동시에 처리해야하는 다중 사용자 채팅 같은 프로젝트에서 작업하고 있습니다. 클라이언트가 연결되면 연결이 accept()이되어 self.socket.recv(1024) 루프가있는 들어오는 데이터를 처리하는 자체 스레드에서 Client 클래스로 전달합니다. 데이터가 들어 오면 data-queue이라는 목록에 저장됩니다. 그런 다음이 클라이언트를 Clients의 목록에 저장합니다.연결을 수락 할 때 여러 개의 소켓이 만들어 지지만 데이터는 연결된 첫 번째 클라이언트가 보낸 것처럼 처리됩니다.

100ms마다 한 번, 내 Clients 목록에있는 모든 Client을 반복하고 data-queue 목록이 비어 있는지 확인하십시오. 그렇지 않다면, 나는 pop() -ing과 클라이언트 주소로 얻은 것을 인쇄합니다.

많은 클라이언트가 동시에 연결하면 첫 번째로 연결된 Client만이 자신이 보낸 모든 데이터를받은 것처럼 보냅니다.

클라이언트 A가 "Hi!" 클라이언트 B가 "안녕하세요!"라고 말하면 서버는 클라이언트 A가 "안녕하세요!"라는 메시지를 보낸 것처럼 읽습니다. 및 "안녕하세요!" 클라이언트 B는 전체 시간 동안 침묵했다. 클라이언트 A의 연결이 끊어지면 추가 클라이언트의 모든 입력은 첫 번째로 남은 클라이언트 (이 경우에는 클라이언트 A가 남은 클라이언트 B)에 의해 보내진 것처럼 처리됩니다.

무엇이 될 수 있습니까?

편집 :

소스 코드는 다음과 같이 다소 간다 :

CLIENTS = [] 

def main(): 
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    s.bind(('', 1515)) 
    s.listen(5) 
    runCycle() 
    while True: 
     CLIENTS.append(client(s.accept())) 
     CLIENTS[len(CLIENTS)-1].start() 

class client(threading.Thread): 
    dataQueue = [] 

    def __init__(self, (socket, address)): 
     self.socket = socket 
     self.address = address 
     threading.Thread.__init__(self) 

    def run(self): 
     self.data = "" 
     while True: 
      self.data = self.socket.recv(1024) 
      if not self.data: 
       break 
      dataQueue.append(self.address + " " + self.data) 
      self.data = "" 

def runCycle(): 
    threading.Timer(0.1, runCycle).start() 
    for c in CLIENTS: 
     if len(c.dataQueue) > 0: 
      print c.dataQueue.pop() 

main() 
+0

정보가 너무 적 으면 고객의 코드를 게시 할 수 있습니까? –

+0

있습니다! 감사합니다 ~ – Maralis

답변

1
class client(threading.Thread): 
    dataQueue = [] 

dataQueue 정적이며 []의 동일한 인스턴스 스레드간에 공유되는 것을 의미한다. 고객의 반복하는 것은이 경우에 효과가없는 것입니다, 당신은 단지 모든 클라이언트 객체에서 읽을 수 있습니다

>>> class C(object): 
... a = [] 
... 
>>> c1, c2 = C(), C() 
>>> c1.a.append(1) 
>>> c2.a 
[1] 

이동 dataQueue__init__에이 문제를 해결 할 수 있습니다.

class client(threading.Thread): 

    def __init__(self, (socket, address)): 
     self.socket = socket 
     self.address = address 
     self.dataQueue = [] 
     threading.Thread.__init__(self) 

그리고 a lockself.dataQueue를 지키고 들여다하시기 바랍니다. 확률은 스레드로부터 안전하지 않습니다.

+0

오! 나는 클래스 내에서 선언 된 변수가 private C++ 클래스 변수처럼 작동한다고 생각했다. 오늘 나는 배운다. 너는 나를 구 했어. 고마워! – Maralis