thrift server端获取客户端ip python

来源:互联网 发布:2017网络交易管理办法 编辑:程序博客网 时间:2024/05/29 19:36
真是费了我九牛二虎之力,终于搞定

网上有说如下方式获取的
classCustomTProcessor(TProcessor):
   defprocess_in(self, iprot):
        api, type, seqid = iprot.read_message_begin()
       ifapinot inself._service.thrift_services:
            iprot.skip(TType.STRUCT)
            iprot.read_message_end()
           returnapi, seqid, TApplicationException(TApplicationException.UNKNOWN_METHOD),None # noqa

       args =getattr(self._service, api +"_args")()
        args.read(iprot)
        iprot.read_message_end()
        result =getattr(self._service, api +"_result")()

       # convert kwargs to args
       api_args = [args.thrift_spec[k][1]forkinsorted(args.thrift_spec)]

       # get client IP address
       client_ip, client_port = iprot.trans.sock.getpeername()

       defcall():
            f =getattr(self._handler, api)
           returnf(*(args.__dict__[k]forkinapi_args),client_ip=client_ip)

        return api, seqid, result,call

关键就在于
iprot.trans.sock.getpeername()

但实测不行,应该是我的版本原因吧

根据这个思路,应该要在processor = ProducerService.Processor(personServiceHandler)
此处获取

1.classProcessor(Iface, TProcessor):
 def__init__(self, handler):
   self._handler = handler
   self._processMap = {}
   self._processMap["sendSync"] = Processor.process_sendSync
   self._processMap["sendAsync"] = Processor.process_sendAsync

 defprocess(self, iprot, oprot):
    (name, type, seqid) = iprot.readMessageBegin()
    print str(iprot.trans)
此处加断点调试,看iprot是啥

trans下面

有socket,是否这样就可以打出来呢
把iprot.trans._TFramedTransport__trans打印,发现服务端报错(实际可能是我少打了一个下划线,所以服务端报错了,被自己坑了)
thrift 服务端报错很不友好,不会报具体位置,只是打印有问题。
然后想,这里不能打,thrift是基于tcp的连接,肯定是socket连接,就一定有对方的ip,port,
我们知道socket连接建立,服务端是指accept这一步拿到新的fd,即新的socket,那就到这一步来找

2.通过单步调试,可以看到是在这一步accept的
classTSimpleServer(TServer):
 """Simple single-threaded server that just pumps around one transport."""

 def__init__(self, *args):
    TServer.__init__(self, *args)

 defserve(self):
   self.serverTransport.listen()
   whileTrue:
      client =self.serverTransport.accept()
     if notclient:
       continue
     itrans =self.inputTransportFactory.getTransport(client)
      otrans =self.outputTransportFactory.getTransport(client)
      iprot =self.inputProtocolFactory.getProtocol(itrans)
      oprot =self.outputProtocolFactory.getProtocol(otrans)
     try:
       whileTrue:
         self.processor.process(iprot, oprot)
     exceptTTransport.TTransportExceptionas tx:
       pass
      exceptExceptionasx:
        logger.exception(x)

      itrans.close()
      otrans.close()
这时候可以看到client就是个socket的实例。
根据之前的经验,thrift的socket获取还需要加handle,所以此处加入打印
printclient.handle.getpeername(),client.host
再调试,发现轻松打印出来了对方ip port和自己的
('10.94.96.140', 43046) localhost

3.实现
知道在哪可以拿到了,那么就想办法取了,
首先重新写一个server
classabServer(TServer.TSimpleServer):
   defserve(self):
       self.serverTransport.listen()
       whileTrue:
            client =self.serverTransport.accept()
           if notclient:
               continue
           itrans =self.inputTransportFactory.getTransport(client)
            otrans =self.outputTransportFactory.getTransport(client)
            iprot =self.inputProtocolFactory.getProtocol(itrans)
            oprot =self.outputProtocolFactory.getProtocol(otrans)
           try:
               whileTrue:
                   self.processor.process(iprot, oprot,client)
           exceptTTransport.TTransportExceptionas tx:
               pass
            exceptExceptionasx:
                logger.exception(x)

            itrans.close()
            otrans.close()
目的是把client传递下去
然后重写process函数
classProcessor(Iface, TProcessor):
 def__init__(self, handler):
   self._handler = handler
   self._processMap = {}
   self._processMap["sendSync"] = Processor.process_sendSync
   self._processMap["sendAsync"] = Processor.process_sendAsync

 defprocess(self, iprot, oprot,client):
    (name, type, seqid) = iprot.readMessageBegin()
   printclient.handle.getpeername(),client.host
    if namenot inself._processMap:
这样就可以用了
('10.94.96.140', 43046)
这就更好了,可以把原理加的参数传递去掉,不用改太底层了。

5.总结,底层原理懂了,知道在哪一步肯定能拿到,再反推看看尽量不改的情况下拿到。 
原创粉丝点击