2011-11-26 4 views
0

SocketClientThread 참조 큐. (thanks again Eli!)다중 스레드 소켓 연결/

하나의 스레드가 훌륭하게 작동하지만 동시에 여러 SocketClientThread 객체를 관리하려고합니다.

연결 후, 두 번째 객체에 데이터를 보내려고하면 SocketClientThread.socket에 sendall 속성이 없다는 메시지가 표시되므로 소켓이 꺼져 있다고 생각합니다.

1과 2 모두의 서버가 성공적으로 연결을 수신하지만 오류를 트리거하는 것은 두 번째 서버의 send 명령입니다.

어떻게이 클래스를 여러 객체와 함께 재사용 할 수 있습니까? 여기

출력입니다 :

$ python testmodule.py 
('sct1: ', 1, None) 
('sct1: ', 1, 'tuxy') 
('sct2: ', 1, None) 
Exception in thread Thread-2: 
Traceback (most recent call last): 
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/threading.py", line 522, in __bootstrap_inner 
    self.run() 
    File "testmodule.py", line 59, in run 
    self.handlers[cmd.type](cmd) 
    File "testmodule.py", line 115, in _handle_SEND 
    self.socket.sendall(header + cmd.data) 
AttributeError: 'NoneType' object has no attribute 'sendall' 

그리고 여기 내 코드는 모두 개방하려고 : 들어

if __name__ == "__main__": 
    sct1 = SocketClientThread() 
    sct1.start() 
    sct1.cmd_q.put(ClientCommand(ClientCommand.CONNECT, ('', 50007))) 
    reply = sct1.reply_q.get(True) 
    sct1.cmd_q.put(ClientCommand(ClientCommand.SEND, "hellothere from sct1")) 
    reply = sct1.reply_q.get(True) 
    print('sct1: ', reply.type, reply.data) 
    sct1.cmd_q.put(ClientCommand(ClientCommand.RECEIVE, "hellothere from sct1")) 
    reply = sct1.reply_q.get(True) 
    print('sct1: ', reply.type, reply.data) 

    sct2 = SocketClientThread() 
    sct2.start() 
    sct2.cmd_q.put(ClientCommand(ClientCommand.CONNECT, ('', 50008))) 
    reply = sct2.reply_q.get(True) 
    print('sct2 connect: ', reply.type, reply.data) 
    sct2.cmd_q.put(ClientCommand(ClientCommand.SEND, "hellothere from sct2")) 
    reply = sct2.reply_q.get(True) 
    print('sct2 send: ', reply.type, reply.data) 
    sct2.cmd_q.put(ClientCommand(ClientCommand.RECEIVE, "hellothere from sct2")) 
    reply = sct2.reply_q.get(True) 
    print('sct2: ', reply.type, reply.data) 

    #close connection 1 
    sct1.cmd_q.put(ClientCommand(ClientCommand.CLOSE)) 
    reply = sct1.reply_q.get(True) 
    print('sct1 close: ', reply.type, reply.data) 

    #close connection 2 
    sct2.cmd_q.put(ClientCommand(ClientCommand.CLOSE)) 
    reply = sct2.reply_q.get(True) 
    print('sct2 close: ', reply.type, reply.data) 

답변

2

샘플 코드에서 버그를 발견 한 것처럼 보입니다 :-) 버그는 사용자가 지적한 것처럼 동시에 두 개 이상의 스레드가 생성 된 경우에만 발생합니다. 이것은 Queue.Queue() 기본 인수가 클래스가 정의 될 때 한 번만 생성되기 때문입니다. 사실 Python의 일반적인 버그이지만 실제로는 목록에서 발생합니다.

내가 게시물을 업데이트했지만 변화가 여기에 있습니다 : 큐는 이제 초기화하는 방법

def __init__(self, cmd_q=None, reply_q=None): 
    super(SocketClientThread, self).__init__() 
    self.cmd_q = cmd_q or Queue.Queue() 
    self.reply_q = reply_q or Queue.Queue() 
    self.alive = threading.Event() 
    self.alive.set() 
    self.socket = None 

    self.handlers = { 
     ClientCommand.CONNECT: self._handle_CONNECT, 
     ClientCommand.CLOSE: self._handle_CLOSE, 
     ClientCommand.SEND: self._handle_SEND, 
     ClientCommand.RECEIVE: self._handle_RECEIVE, 
    } 

주 -는 가변 기본 인수 잡았다을 피하기 위해 공통의 관용구이다.

귀하의 샘플 코드는


추신 : 지금 나를 위해 작동 내 Windows 컴퓨터에서 성공적으로 연결할 수있는 클라이언트에서 호스트 (심지어 경우 localhost) 지정해야합니다.

+0

감사합니다. 내 소켓 및 대기열이 모두 예상대로 작동하고 있음을 확인했습니다. 대기열이 생성 된 방법이 마음에 들었지만 소켓을 죽일 수있는 방법을 이해할 수 없었습니다. 나는 그들이 같은 큐 객체를 공유하고있는 것을 본다. 고맙습니다! – Coder1

+0

@ Coder1 : 그래, 다른 스레드가 첫 번째 소켓을 죽일 요청을 받았고 자신의 소켓을 죽였지 만 보내기/받기 요청을 받았다. –

+0

그냥 호출해서는 안된다. 스레드를 종료하려면 부모 개체에서 mysocketclientthread.join()? 나는 그 두 가지를 시도하고 결합을위한 큐 핸들러를 추가했다. 응용 프로그램이 중단되고 부모 개체가 설정되지 않은 것처럼 보입니다. 어쩌면 다시 좋은 의견이 아니기 때문일 수도 있습니다. – Coder1

0

을 멀티 스레드 내가 ZeroMQ을 시도하는 것이 좋습니다 스레드/프로세스 간의 통신을 위해 소켓을 사용하여 프로그래밍 . 비동기 I/O를 쉽게 만들고 자동 대기열을 내장합니다. 여러 스레드가 동시에 GUI 스레드에 메시지를 보내면 메시지는 간단하고 도착할 때 대기 및 처리됩니다. 이게 도움이 되길 바란다.