2013-06-04 3 views
4

더 나은 단어가 부족하여 "대화식"클라이언트/서버 동작을 수행하기 위해 Twisted를 수행하는 방법을 생각하고 있습니다.대화 형 Python 클라이언트/서버 Twisted

서비스에 연결하는 프로토콜 및 ClientFactory 클래스를한데 모으고 즉각적인 쿼리/응답을 수행했습니다 (connectionMade -> self.queryStatus 참조). 이것은 예상대로 성공하고 Factory 클래스의 서버 응답을 인쇄합니다.

이제 내 문제는 잠재적 인 수신 데이터를 수신하면서 데이터를 보내야하는 외부 이벤트가 발생한다는 것입니다. 하지만 일단 reactor.run() 루프가 진행되면 내 응용 프로그램의 나머지 부분이 데이터 전송을 시작하는 방법을 알지 못합니다.

난 이후 몇 가지 다른 방법을 시도했지만,이 설명 된대로 RECV 부분을 처리했던 간단한 방법입니다 :

class myListenerProtocol(LineReceiver): 
    delimiter = '\n' 

    def connectionMade(self): 
     print("Connected to: %s" % self.transport.getPeer()) 
     self.queryStatus(1) 

    def dataReceived(self, data): 
     print("Receiving Data from %s" % self.transport.getPeer()) 
     ... 
     self.commandReceived(self.myData) 

    def commandReceived(self, myData): 
     self.factory.commandReceived(myData) 

    def connectionLost(self, reason): 
     print("Disconnected.") 

    def queryStatus(self, CommandValue): 
     ... 
     strSend = CommandValue # or some such 
     self.transport.write(strSend) 

class mySocketFactory(ClientFactory): 
    protocol = myListenerProtocol 

    def __init__(self): 
     pass 

    def buildProtocol(self, address): 
     proto = ClientFactory.buildProtocol(self, address) 
     return proto 

    def commandReceived(self, myData): 
     print myData 
     reactor.stop() # It won't normally stop after recv 

    def clientConnectionFailed(self, connector, reason): 
     print("Connection failed.") 
     reactor.stop() 


def main(): 
    f = mySocketFactory() 
    reactor.connectTCP("10.10.10.1", 1234, f) 
    reactor.run() 

나는이 꽤 솔직 상상하지만, 많은에 수많은 시간 예제와 문서는 내가이 시나리오를 어떻게 다루어야하는지 잘 이해하지 못하고 나를 떠났습니다.

답변

-1

글쎄, 거기에 접근하는 방법이 많이 있습니다. 가장 좋은 방법은 실제로 응용 프로그램의 컨텍스트에 따라 달라 지므로 여기서는이 방법 중 하나를 자세히 설명하지는 않지만 제가 최근에 읽은 책 해커의 뉴스 : 당신이 작업을하는지에 적용되지 않을 수도 있지만

좋은 사용의 경우 예를 들어, (또는 당신이 그것을 읽고 있습니다) :

BTW, 당신은 또한 일의 종류를 처리에서 좋은 gevent이나 토네이도를 살펴있을 수 있습니다. 다른 "이벤트"(GTK 또는 QT 같이) GUI 툴킷에서 경우에 당신은 단지 명령 줄 이벤트를 원하는 경우에도

당신이 조심 여전히 스레드를 필요거야 GIL정말 조심하고, 그것의.

마지막으로, 더 많은 상호 작용을 원할 경우 작업중인 다양한 유스 케이스 (GUI에 연결하는 하나의 클라이언트, 다른 하나는 CLI가 있고 다른 하나는 데이터베이스가 있고 다른 하나는 SAAS의 API 등이 있습니다.)

즉, 디자인이 작동하지 않는다면, 당신의 관점을 바꾸어보십시오!

+0

GIL에주의하지 않아도됩니다. 스레드를 사용하지 마십시오. 이 게시물에 관한 내용은 스레드에 대한 필요성을 암시하지 않으므로 GIL은 부적절합니다. – Glyph

1

이제 내 문제는 잠재적 인 수신 데이터를 항상 수신하면서 데이터를 전송해야하는 외부 이벤트가 발생한다는 것입니다. 하지만 일단 reactor.run() 루프가 진행되면 내 응용 프로그램의 나머지 부분이 데이터 전송을 시작하는 방법을 알지 못합니다.

"외부 이벤트"? 무엇처럼? 연결에 데이터가 도착합니까? 위대한, 원자로를 가동시키는 것은 실제로 그 데이터를 처리 할 수 ​​있음을 의미합니다.

아니면 누군가 GUI에서 버튼을 클릭하고 있습니까?GUI 통합 리액터 중 하나를 사용해보십시오. 다시, 리액터가 작동 할 때까지는 이러한 이벤트를 처리 할 수 ​​없습니다.

주 기능이 reactor.run()이고 다른 하나는 이 수행해야한다고 생각하기 때문에 계속 걸려 넘어지고 있습니다.. 이것은 어떻게 작동하지 않습니다. 이벤트 중심 프로그램을 작성할 때 모든 이벤트 소스를 정의한 다음 해당 소스에 이벤트가 도착하면 이벤트 루프가 핸들러를 호출하도록합니다.

+1

아니, 내가 의미하는 바는 내가 더 큰 응용 프로그램의 구성 요소로 포함시킬 것임을 의미한다. 예를 들어 GUI로 구동되는 메인 애플리케이션을 사용하는 동안 백그라운드에서 연결되고 실행되는 클라이언트 구성 요소라고 가정 해 보겠습니다. 따라서 주 (기존) 응용 프로그램에서 이벤트가 발생합니다. 어떤 것을 트리거하는지는 중요하지 않지만 연결된 클라이언트 세션이 데이터를 보내 게됩니다. 그 사이에, 그것은 수신 연결을 받아 들일 것이고 나는 그것들을 처리해야 할 것이다. – Dave

+0

그것은 다른 구성 요소를 통합하는 방법을 결정할 것이기 때문에 트리거하는 것이 중요합니다. 다른 구성 요소가 어떻게 구현되는지 완전히 무시하려면 별도의 프로세스에서 실행하고 일종의 IPC/RPC를 사용하십시오. 일반적으로 더 많은 작업이 필요하지만, 각 구성 요소의 구현 방법에 대해 전혀 지정하지 않으려면 두 구성 요소를 함께 사용하는 것이 가장 직접적인 방법입니다. –

+0

그리고 확실하지 않은 경우에는 다른 구성 요소의 작동 방식을 지정한 다음 Twisted 이벤트 루프에 통합하는 방법을 찾아야한다고 생각합니다. 위의 의견은 당신이 그렇게하지 않을 경우를 대비 한 것입니다. –