2014-01-27 6 views
3

Twisted의 최상위 서버에서 사용할 TCP 기반 프로토콜을 구현하고 싶습니다. 이러한 프로토콜 구현의 메커니즘은 분명합니다 (프로토콜을 상속하고 4 개의 상속 된 메소드를 덮어 쓰고 Factory를 빌드합니다).Python Twisted : 처리와 별도의 프로토콜

  • 프로토콜 :

    그러나, 내 프로토콜이있는 방식으로, 애플리케이션 로직에서 분리되고 싶어요, 파이썬 데이터 구조를 클라이언트에서 데이터를 수신 바이트 스트림을 디코딩하고 채워은 데이터 구조를 취 바이트 스트림을 인코딩하는 (텍스트 기반) 및 클라이언트

  • 애플리케이션 로직 반응 : 상기 데이터 구조를 수신 및 평가 반환 응답 데이터 구조

Twisted 응용 프로그램을 다른 응용 프로그램에 의존하지 않게 만드는 방법은 무엇입니까? 느슨한 결합)? 나는 프로토콜 클래스가 매개 변수로 응용 프로그램 논리 콜백으로 인스턴스화 될 것이라고 생각하겠습니까?

편집 :

from twisted.internet.protocol import Protocol 
from twisted.internet.protocol import Factory 
from twisted.internet.endpoints import TCP4ServerEndpoint 
from twisted.internet import reactor 

class Logic: 
    def process(self, data): 
     return "Processed: %s" % data 

class LineProtocol(Protocol): 
    def dataReceived(self, data): 
     print "Received: %s" % data 
     if self.factory._logic_callback: 
      ret = self.factory._logic_callback.process(data) 
      print "Sent: %s" % ret 
      self.transport.write(ret) 

class LineFactory(Factory): 
    protocol = LineProtocol 

    def __init__(self, logic_callback = None): 
     if logic_callback: 
      self._logic_callback = logic_callback() 
     else: 
      self._logic_callback = None 

endpoint = TCP4ServerEndpoint(reactor, 1234) 
endpoint.listen(LineFactory(Logic)) 
reactor.run() 

이는 "트위스트"방법을 고려겠습니까 : 한편

,이 있나요? 개선 할 것이 있다면?

이 코드는 LineFactory 내에 Logic 인스턴스를 만듭니다. 거기에 넣는 것이 좋습니까?

+0

지금까지 무엇을 얻었습니까? – SingleNegationElimination

+0

'process'는 임의의 라이브러리를 사용하는 어떤 언어의 메소드에 대해서 가능한 최악의 이름 중 하나입니다. –

+0

@ Jean-PaulCalderone : 동의합니다.이 예제 문맥에서 저를 사용하는 것에 대해 저를 용서해주십시오. – Bernd

답변

3

계획에 이미 느슨한 결합의 한 예가 있습니다. TCP의 구현 세부 사항을 처리하는 전송은 사용자의 프로토콜과 별개이며 두 객체는 ​​잘 정의 된 인터페이스 인 dataReceived 등 프로토콜에서 상호 작용합니다 (전송시 write 외).

이 아이디어를 다른 단계로 확장하십시오. 애플리케이션 객체와 프로토콜이 잘 정의 된 인터페이스를 통해 상호 작용하도록하십시오. 응용 프로그램 개체가 __init__ 인수로 프로토콜에 제공되는지 여부는 예상되는 상호 작용에 따라 다소 다릅니다. 응용 프로그램이 순전히 반응 적이면 (즉, 프로토콜에서 일어나는 일들에 반응 할뿐 아니라 자체적으로 일을 시작하지 않습니다) 그러면 이것은 좋은 접근 방법입니다. 응용 프로그램이 동작을 유도하는 데 더 관심이있는 경우 (예 : HTTP 클라이언트 프로토콜을 실행하는 응용 프로그램을 고려하십시오. 응용 프로그램에서 요청을 보내려는 것으로 판단 할 때까지 네트워크에서 아무 일도 발생하지 않습니다) 그러면 인터페이스를 명확하게 정의 할 수 있습니다 (예 : HTTP 클라이언트 프로토콜에 URL, HTTP 메서드 등을 사용하는 request 메서드가있을 수 있습니다).

새로 프로토콜 인스턴스를 돌려주는 좋은 API가 있다는 것을 명심하십시오. 예를 들어 :

from sys import argv 

from twisted.internet.protocol import Protocol 
from twisted.internet.endpoints import connectProtocol, clientFromString 
from twisted.internet.task import react 

def main(reactor, description): 
    endpoint = clientFromString(reactor, description) 
    connecting = connectProtocol(endpoint, Protocol()) 
    def connected(protocol): 
     # Now `protocol` is connected somewhere and you can start 
     # calling useful methods on it, if it has any. 
     ... 
    connecting.addCallback(connected) 
    return connecting 

react(main, argv[1:]) 

connected에 몇 가지 유용한 코드를 삽입하여 더 흥미 프로토콜 클래스의 인스턴스와 Protocol()을 교체하고 an argument like로 "TCP : 로컬 호스트 : 25"를 실행합니다. 귀하의 예제에서

는 :

def dataReceived(self, data): 
    print "Received: %s" % data 
    if self.factory._logic_callback: 
     ret = self.factory._logic_callback.process(data) 
     print "Sent: %s" % ret 
     self.transport.write(ret) 

이 정말 도움이되지 않습니다.프로토콜에 실제로 프로토콜 로직을 구현하지 않았습니다. 당신이 한 것은 self.factory._logic_callback이 프로토콜을 구현할 책임이 있다는 것입니다. 실질적인 이익을위한 몇 가지 추가 개체입니다. 나는 이런 식으로 일할 것을 제안하지 않을 것이다.

프로토콜 클래스에서 모든 구문 분석 및 직렬화를 수행하려고합니다. 구조화 된 객체 (사용자가 수행하는 구문 분석의 결과)로 구현 된 상위 수준의 논리를 프로토콜 이외의 객체에만 위임하십시오.