Получить адрес сверстника внутри функции обработчика комиссионных - PullRequest
0 голосов
/ 02 октября 2011

Я реализую небольшой сервер (0.6.0) в ruby, чтобы играть роль прокси для другого протокола с несколькими подключениями (несколькими клиентами) к одному серверу.Я хочу иметь возможность хранить данные для каждого клиента на стороне сервера и отслеживать параметры «сеанса» по нескольким вызовам функций-обработчиков.

В настоящее время я использую Thrift::NonblockingServer, так как SimpleServer не позволяет одновременноподключений.

Я знаю, как использовать TCPSocket::peeraddr, но Thrift::NonblockingServer::IOManager::Worker::run создает временный MemoryBufferTransport с прочитанным фреймом и передает его в качестве протокола ввода / вывода в процессор, поэтому кажется, что информацияне передается оттуда.

Есть ли чистый способ сделать это?Я думал о том, чтобы переопределить вышеупомянутый Thrift::NonblockingServer::IOManager::Worker::run, чтобы он также включал fd или другой идентификатор в качестве дополнительного параметра для обработки или дополнения прототипов, но я также должен беспокоиться об одном слое сгенерированного кода ruby ​​(process_* методы в class Processor) это кажется немного тяжелым.

Интересно, делал ли кто-нибудь что-то подобное раньше.

Спасибо!

ps, это похоже на проблему этот вопрос C ++ экономный

1 Ответ

0 голосов
/ 08 октября 2011

Вот как я изменил Thrift::NonblockingServer::IOManager::Worker::run для поддержки этого.

Несколько предостережений:

  • Как я уже упоминал в этом вопросе, я не считаю его чистым (если ничего другого мне не придется отслеживать будущие версии Thrift на предмет изменений в этой функции, это основано на 0.6.0).
  • это написано для работы с ruby ​​1.8 (или я бы получил непереведенный адрес / порт см. Мой другой вопрос )
  • Я рубиновый новичок .. Я уверен, что я сделал кое-что из этого "неправильно" (например, должен ли $connections быть @@connections в ConnEntry или классом diff?).
  • Мне известно, что хэш Thread.current для локального хранилища потоков имеет проблему загрязнения пространства имен

Сначала в каком-то центральном модуле:

module MyThriftExt

  $connections={}

  class ConnEntry
    attr_reader :addr_info, :attr

    def initialize(thrift_fd)
      @addr_info=thrift_fd.handle.peeraddr
      @attr={}
    end

    def self.PreHandle(fd)
      $connections[fd]=ConnEntry.new(fd) unless $connections[fd].is_a? ConnEntry
      # make the connection entry as short-term thread-local variable 
      # (cleared in postHandle)
      Thread.current[:connEntry]=$connections[fd]
    end

    def self.PostHandle()
      Thread.current[:connEntry]=nil
    end

    def to_s()
      "#{addr_info}"
    end   end end


module Thrift   class NonblockingServer
    class IOManager
      alias :old_remove_connection :remove_connection
      def remove_connection(fd)
        $connections.delete fd
        old_remove_connection(fd)
      end

      class Worker
        # The following is verbatim from thrift 0.6.0 except for the two lines 
        # marked with "Added"
        def run
          loop do
            cmd, *args = @queue.pop
            case cmd
            when :shutdown
              @logger.debug "#{self} is shutting down, goodbye"
              break
            when :frame
              fd, frame = args
              begin
                otrans = @transport_factory.get_transport(fd)
                oprot = @protocol_factory.get_protocol(otrans)
                membuf = MemoryBufferTransport.new(frame)
                itrans = @transport_factory.get_transport(membuf)
                iprot = @protocol_factory.get_protocol(itrans)
                MyThriftExt::ConnEntry.PreHandle(fd)    # <<== Added
                @processor.process(iprot, oprot)
                MyThriftExt::ConnEntry.PostHandle       # <<== Added
              rescue => e
                @logger.error "#{Thread.current.inspect} raised error: #{e.inspect}\n#{e.backtrace.join("\n")}"
              end
            end
          end
        end
      end
    end   
  end
end

Затем в любой точке обработчика вы можете получить доступ к Thread.current[:connEntry].addr_info для данных, специфичных для соединения, или сохранить все, что касается соединения, в хэше Thread.current[:connEntry].attr.

...