«Отслеживание» связей с Thrift - PullRequest
1 голос
/ 14 апреля 2010

Я пытаюсь создать игру, используя Thrift, чтобы клиенты были игроками, а сервер управлял досками, как this .Тем не менее, я не могу понять, как сервер Thrift Facebook может «отслеживать» пользователя, то есть при вызове attack() на их службе мне не нужно снова идентифицировать себя.

то, что предлагает созданная заглушка сервера, сделать это невозможно:

int main(int argc, char **argv) {
  int port = 9090;
  shared_ptr<ConnectFourHandler> handler(new ConnectFourHandler());
  shared_ptr<TProcessor> processor(new ConnectFourProcessor(handler));
  shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
  shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
  shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());

  TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
  server.serve();
  return 0;
}

В этом примере для сервера создается только один обработчик, и именно сервер принимает соединения.

Как Facebook может отслеживать, какие клиенты подключены к серверу, если все запросы направляются только через один обработчик на сервер?

Ответы [ 2 ]

0 голосов
/ 31 июля 2018

Поскольку Thrift использует уникальный поток для каждого соединения, можно использовать идентификатор потока, чтобы связать их вместе. Насколько я знаю, нет способа сделать это из самого бережливости. Imo это было бы возможно, если бы thrift передавал поле контекста каждой функции-обработчику.

Вот пример, который использует идентификатор потока:

#include <map>
#include <thread>

typedef struct {
    // you would put your connection specific variables here
} ConnectionContext;

// You could reverse these types if you had more than one
// context per thrift connection, eg. your service involved opening
// or connecting to more than one thing per thrift connection
std::map<std::thread::id, ConnectionContext> threadContextMap;

class OurEventHandler : public server::TServerEventHandler {
public:
OurEventHandler() :
    NumClients_(0)
{}

//Called before the server begins -
//virtual void preServe() {}

//createContext may return a user-defined context to aid in cleaning
//up client connections upon disconnection. This example dispenses
//with contextual information and returns NULL.
virtual void* createContext(shared_ptr<protocol::TProtocol> input, 
shared_ptr<protocol::TProtocol> output)
{
    printf("Client connected (total %d)\n", ++NumClients_);

    auto this_id = std::this_thread::get_id();
    std::cout << "connected thread " << this_id << std::endl;

    return NULL;
}

//Called when an client has disconnected, either naturally or by error.
virtual void deleteContext(void* serverContext, 
shared_ptr<protocol::TProtocol>input, shared_ptr<protocol::TProtocol>output)
{
    printf("Client disconnected (total %d)\n", --NumClients_);

    auto this_id = std::this_thread::get_id();
    std::cout << "disconnected thread " << this_id << std::endl;

    auto context = threadContextMap[this_id];

    // TODO: Perform your context specific cleanup code here
}

protected:
    uint32_t NumClients_;
};


class yourRpcHandler : virtual public service_rpcIf
{
public:
    yourRpcHandler() :
    {
        // Your initialization goes here
    }

    void SomeMethod()
    {
        auto context = threadContextMap[std::this_thread::get_id()];

        // TODO: use the context as you see fit
    }
};

int main(int argc, char **argv)
{
    int port = 9090;
    printf("Listening on port %d\n", port);

    auto rpcHandler = new yourRpcHandler();
    shared_ptr<yourRpcHandler> handler(rpcHandler);
    shared_ptr<TProcessor> processor(new yourRpcProcessor(handler));
    shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
    shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
    shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());

    TThreadedServer server(processor, serverTransport, transportFactory, protocolFactory);
    shared_ptr<OurEventHandler> EventHandler(new OurEventHandler());

    server.setServerEventHandler(EventHandler);
    server.serve();
    return 0;
}
0 голосов
/ 13 апреля 2011

Попробуйте server.setServerEventHandler. Он будет вызывать ваш код при подключении нового клиента, давая вам возможность создать объект контекста для конкретного соединения.

...