6

I'm tring to provide a remote server by thrift, and below is my server-side trial:

from test_thrift.test_server.TestService import Iface,Processor
from thrift.Thrift import TType,TException
from thrift.Thrift import TProcessor
from thrift.transport import TSocket
from thrift.protocol import TBinaryProtocol
from thrift.server import TNonblockingServer


port = int(config["server"]["port"])
handler = SmbService()
processor = Processor(handler)
socket = TSocket.TServerSocket(port=port)
server = TNonblockingServer.TNonblockingServer(processor, socket)

server.setNumThreads(100)
server.serve()

At my client-side, for every request I will create a new connect and close it after got response from server.

from thrift.transport.TSocket import TTransportException
from thrift.Thrift import TException
from thrift.protocol import TBinaryProtocol, TCompactProtocol
from thrift.transport import TTransport
from thrift.transport import TSocket
from thrift import Thrift
from test_thrift.test_server import TestService


class SmbClient(object):
    def __init__(self):
        try:
            self.tsocket = TSocket.TSocket(settings.THRIFT_HOST, settings.THRIFT_PORT_PRODUCT)
            self.transportFactory = TTransport.TFramedTransportFactory()
            self.transport = self.transportFactory.getTransport(self.tsocket)
            self.protocol = TBinaryProtocol.TBinaryProtocol(self.transport)
            self.client = TestService.Client(self.protocol)
            self.transport.open()
        except Thrift.TException as e:
            self.logger.info(e)


class BaseService(object):

    def __init__(self):
        self.commonLogger = logging.getLogger('ads')
        self.header = "header111"

    def search_ads_list(self, request, account_id):
        self.smbClient.client.getFBAdsByAccount(param1, param2)

    def __enter__(self):
        self.smbClient = SmbClient()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.smbClient.transport.close()

ech request call is like this:

 with BaseService() as BaseSingleService:
            status, data, info = BaseSingleService.search_ads_list(
                request, account_id)

The actual amount of requests from client are not big enough , but after period of time. I got error like :

Traceback (most recent call last):
  File "/home/xxx/xxx/src/smb_thrift_server.py", line 2200, in <module>
    server.serve()
  File "/home/xxx/xxx/venv3/lib/python3.5/site-packages/thrift/server/TNonblockingServer.py", line 350, in serve
    self.handle()
  File "/home/xxx/xxxx/venv3/lib/python3.5/site-packages/thrift/server/TNonblockingServer.py", line 310, in handle
    rset, wset, xset = self._select()
  File "/home/luban/smb_thrift_server/venv3/lib/python3.5/site-packages/thrift/server/TNonblockingServer.py", line 302, in _select
    return select.select(readable, writable, readable)
ValueError: filedescriptor out of range in select()

Why error happended as I've closed the client connect each time after receiving the response?

update TestService codes below:

#
# Autogenerated by Thrift Compiler (0.9.1)
#
# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
#
#  options string: py:new_style
#

from thrift.Thrift import TType, TMessageType, TException, TApplicationException
from .ttypes import *
from thrift.Thrift import TProcessor
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol, TProtocol
try:
  from thrift.protocol import fastbinary
except:
  fastbinary = None


class Iface(object):

    """..."""

    def getFBAdsByAccount(self, header, account_id, effective_status, access_token):
        """
        Parameters:
         - header
         - account_id
         - effective_status
         - access_token
        """
        pass

    """..."""


class Client(Iface):
  def __init__(self, iprot, oprot=None):
    self._iprot = self._oprot = iprot
    if oprot is not None:
      self._oprot = oprot
    self._seqid = 0

  def getFBAdsByAccount(self, header, account_id, effective_status, access_token):
    """
    Parameters:
     - header
     - account_id
     - effective_status
     - access_token
    """
    self.send_getFBAdsByAccount(header, account_id, effective_status, access_token)
    return self.recv_getFBAdsByAccount()

  def send_getFBAdsByAccount(self, header, account_id, effective_status, access_token):
    self._oprot.writeMessageBegin('getFBAdsByAccount', TMessageType.CALL, self._seqid)
    args = getFBAdsByAccount_args()
    args.header = header
    args.account_id = account_id
    args.effective_status = effective_status
    args.access_token = access_token
    args.write(self._oprot)
    self._oprot.writeMessageEnd()
    self._oprot.trans.flush()

  def recv_getFBAdsByAccount(self):
    (fname, mtype, rseqid) = self._iprot.readMessageBegin()
    if mtype == TMessageType.EXCEPTION:
      x = TApplicationException()
      x.read(self._iprot)
      self._iprot.readMessageEnd()
      raise x
    result = getFBAdsByAccount_result()
    result.read(self._iprot)
    self._iprot.readMessageEnd()
    if result.success is not None:
      return result.success
    if result.e is not None:
      raise result.e
    raise TApplicationException(TApplicationException.MISSING_RESULT, "getFBAdsByAccount failed: unknown result");

class Processor(Iface, TProcessor):
  def __init__(self, handler):
    self._handler = handler
    self._processMap = {}
    self._processMap["getFBAdsByAccount"] = Processor.process_getFBAdsByAccount


  def process(self, iprot, oprot):
    (name, type, seqid) = iprot.readMessageBegin()
    if name not in self._processMap:
      iprot.skip(TType.STRUCT)
      iprot.readMessageEnd()
      x = TApplicationException(TApplicationException.UNKNOWN_METHOD, 'Unknown function %s' % (name))
      oprot.writeMessageBegin(name, TMessageType.EXCEPTION, seqid)
      x.write(oprot)
      oprot.writeMessageEnd()
      oprot.trans.flush()
      return
    else:
      self._processMap[name](self, seqid, iprot, oprot)
    return True


  def process_getFBAdsByAccount(self, seqid, iprot, oprot):
    args = getFBAdsByAccount_args()
    args.read(iprot)
    iprot.readMessageEnd()
    result = getFBAdsByAccount_result()
    try:
      result.success = self._handler.getFBAdsByAccount(args.header, args.account_id, args.effective_status, args.access_token)
    except test_thrift.common.ttypes.ServerException as e:
      result.e = e
    oprot.writeMessageBegin("getFBAdsByAccount", TMessageType.REPLY, seqid)
    result.write(oprot)
    oprot.writeMessageEnd()
    oprot.trans.flush()




class getFBAdsByAccount_args(object):
  """
  Attributes:
   - header
   - account_id
   - effective_status
   - access_token
  """

  thrift_spec = (
    None, # 0
    (1, TType.STRUCT, 'header', (test_thrift.common.ttypes.RequestHeader, test_thrift.common.ttypes.RequestHeader.thrift_spec), None, ), # 1
    (2, TType.STRING, 'account_id', None, None, ), # 2
    (3, TType.LIST, 'effective_status', (TType.STRING,None), None, ), # 3
    (4, TType.STRING, 'access_token', None, None, ), # 4
  )

  def __init__(self, header=None, account_id=None, effective_status=None, access_token=None,):
    self.header = header
    self.account_id = account_id
    self.effective_status = effective_status
    self.access_token = access_token

  def read(self, iprot):
    if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
      fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))
      return
    iprot.readStructBegin()
    while True:
      (fname, ftype, fid) = iprot.readFieldBegin()
      if ftype == TType.STOP:
        break
      if fid == 1:
        if ftype == TType.STRUCT:
          self.header = test_thrift.common.ttypes.RequestHeader()
          self.header.read(iprot)
        else:
          iprot.skip(ftype)
      elif fid == 2:
        if ftype == TType.STRING:
          self.account_id = iprot.readString();
        else:
          iprot.skip(ftype)
      elif fid == 3:
        if ftype == TType.LIST:
          self.effective_status = []
          (_etype24, _size21) = iprot.readListBegin()
          for _i25 in range(_size21):
            _elem26 = iprot.readString();
            self.effective_status.append(_elem26)
          iprot.readListEnd()
        else:
          iprot.skip(ftype)
      elif fid == 4:
        if ftype == TType.STRING:
          self.access_token = iprot.readString();
        else:
          iprot.skip(ftype)
      else:
        iprot.skip(ftype)
      iprot.readFieldEnd()
    iprot.readStructEnd()

  def write(self, oprot):
    if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None:
      oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))
      return
    oprot.writeStructBegin('getFBAdsByAccount_args')
    if self.header is not None:
      oprot.writeFieldBegin('header', TType.STRUCT, 1)
      self.header.write(oprot)
      oprot.writeFieldEnd()
    if self.account_id is not None:
      oprot.writeFieldBegin('account_id', TType.STRING, 2)
      oprot.writeString(self.account_id)
      oprot.writeFieldEnd()
    if self.effective_status is not None:
      oprot.writeFieldBegin('effective_status', TType.LIST, 3)
      oprot.writeListBegin(TType.STRING, len(self.effective_status))
      for iter27 in self.effective_status:
        oprot.writeString(iter27)
      oprot.writeListEnd()
      oprot.writeFieldEnd()
    if self.access_token is not None:
      oprot.writeFieldBegin('access_token', TType.STRING, 4)
      oprot.writeString(self.access_token)
      oprot.writeFieldEnd()
    oprot.writeFieldStop()
    oprot.writeStructEnd()

  def validate(self):
    return


  def __repr__(self):
    L = ['%s=%r' % (key, value)
      for key, value in self.__dict__.items()]
    return '%s(%s)' % (self.__class__.__name__, ', '.join(L))

  def __eq__(self, other):
    return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

  def __ne__(self, other):
    return not (self == other)

class getFBAdsByAccount_result(object):
  """
  Attributes:
   - success
   - e
  """

  thrift_spec = (
    (0, TType.STRUCT, 'success', (test_thrift.common.ttypes.ResponseListMap, test_thrift.common.ttypes.ResponseListMap.thrift_spec), None, ), # 0
    (1, TType.STRUCT, 'e', (test_thrift.common.ttypes.ServerException, test_thrift.common.ttypes.ServerException.thrift_spec), None, ), # 1
  )

  def __init__(self, success=None, e=None,):
    self.success = success
    self.e = e

  def read(self, iprot):
    if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
      fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))
      return
    iprot.readStructBegin()
    while True:
      (fname, ftype, fid) = iprot.readFieldBegin()
      if ftype == TType.STOP:
        break
      if fid == 0:
        if ftype == TType.STRUCT:
          self.success = test_thrift.common.ttypes.ResponseListMap()
          self.success.read(iprot)
        else:
          iprot.skip(ftype)
      elif fid == 1:
        if ftype == TType.STRUCT:
          self.e = test_thrift.common.ttypes.ServerException()
          self.e.read(iprot)
        else:
          iprot.skip(ftype)
      else:
        iprot.skip(ftype)
      iprot.readFieldEnd()
    iprot.readStructEnd()

  def write(self, oprot):
    if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None:
      oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))
      return
    oprot.writeStructBegin('getFBAdsByAccount_result')
    if self.success is not None:
      oprot.writeFieldBegin('success', TType.STRUCT, 0)
      self.success.write(oprot)
      oprot.writeFieldEnd()
    if self.e is not None:
      oprot.writeFieldBegin('e', TType.STRUCT, 1)
      self.e.write(oprot)
      oprot.writeFieldEnd()
    oprot.writeFieldStop()
    oprot.writeStructEnd()

  def validate(self):
    return


  def __repr__(self):
    L = ['%s=%r' % (key, value)
      for key, value in self.__dict__.items()]
    return '%s(%s)' % (self.__class__.__name__, ', '.join(L))

  def __eq__(self, other):
    return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

  def __ne__(self, other):
    return not (self == other)


jia Jimmy
  • 1,693
  • 2
  • 18
  • 38
  • are you calling the server from multiple threads? "filedescriptor out of range in select()" usually means that the process is trying to handle too many connections at once, maybe the sockets aren't getting close – kederrac Aug 30 '19 at 18:46
  • and what is ProductServer ? – kederrac Aug 30 '19 at 18:51
  • @rusu_ro1 Everytime client sould close the connection after called server..So I'm confused with this situation – jia Jimmy Sep 01 '19 at 04:01
  • Who is SmbClient.Client? Can you post somewhere your entire code? – kederrac Sep 01 '19 at 07:47
  • @rusu_ro1 Sorry for my poor mistake, It should be `TestService ` who is the middle service between `cline-side` and `server-side`. – jia Jimmy Sep 01 '19 at 08:18
  • can you put TestService class ? is from your local module test_server.... – kederrac Sep 01 '19 at 09:01
  • @rusu_ro1 Thanks again for your patience, I've updated related codes above..And these codes are automaticlly generated by pre-defined thrift file. – jia Jimmy Sep 03 '19 at 09:40

0 Answers0