twisted web get host:异步响应中的port tuple

时间:2014-11-07 16:57:17

标签: python twisted

我可以使用以下示例制作异步请求: http://twistedmatrix.com/documents/current/web/howto/client.html

我可以在Protocol.dataReceived()中获取异步响应,但是如何找出哪个响应映射到哪个请求?我想将我回复的响应映射到原始主机:port / request。

此外,像我在这里一样使用全球安全吗?

class ClientResponseProtocol(Protocol):

  def __init__(self, whenFinished):
      self.whenFinished = whenFinished

  def dataReceived(self, bytes):
    global BUILD_REVISION

    d = json.loads(bytes)
    bv = d.get("build_revision")

    if bv in BUILD_REVISION:
      BUILD_REVISION[bv] += 1
    else:
      BUILD_REVISION[bv] = 1

  def makeConnection(self, transport):
    pass

  def connectionLost(self, reason):
    self.whenFinished.callback(None)

def handleResponse(r):
  #print("version=%s\ncode=%s\nphrase='%s'" % (r.version, r.code, r.phrase))
  #for k,v in r.headers.getAllRawHeaders():
  #  print(k, v)
  finished = twisted.internet.defer.Deferred()
  r.deliverBody(ClientResponseProtocol(finished))
  return finished

def handleError(reason):
  reason.printTraceback()
  reactor.stop()

def getPage(url):
  d = Agent(reactor).request('GET', url, Headers({'User-Agent': ['user']}), None)
  d.addCallbacks(handleResponse, handleError)
  return d


semaphore = twisted.internet.defer.DeferredSemaphore(BATCH_SIZE)
dl = list()

for server in servers:
  dl.append(semaphore.run(getPage, 'http://%s/server_info.json' % server))

dl = twisted.internet.defer.DeferredList(dl)
dl.addCallbacks(lambda x: reactor.stop(), handleError)

reactor.run()

2 个答案:

答案 0 :(得分:1)

您可以将额外参数传递给Deferred回调:

d.addCallback(f, extra, positional, args, keyword=args)

所以,例如:

def report_result(result, request_url):
    ...

url = 'http://%s/server_info.json' % server
d = getPage(url)
d.addCallback(report_result, request_url=url)

或循环:

list_of_results = []
for server in list_of_servers:
    url = 'http://%s/server_info.json' % server
    d = getPage(url)
    d.addCallback(report_result, request_url=url)
    list_of_results.append(d)

all_requests = DeferredList(list_of_results)
...

另外,您可能还想查看twisted.web.client.Agent以替换您对getPage的使用。

答案 1 :(得分:0)

  • 首先,不要使用全局变量。这是邪恶的。
  • 其次,Twisted为每个连接创建协议实例。因此,您将在Protocol.__init__()中定义的所有属性将是"连接范围"。
  • 第三,每个Protocol实例都应该与transport连接,它描述了连接(例如tcp)。传输对象包含您需要的数据,可以像这样检索:
def makeConnection(self, transport):
    # for a TransportProxyProducer
    host = transport._producer.getPeer().host
    port = transport._producer.getPeer().port

以下是可能有用的api文档的一些链接: