我正在开发一个连接到不同服务器的应用程序,收集数据并显示它。 实际上,我已经创建了它,但感觉我错了,因为它创建了一堆线程,我确实知道它不可扩展。
现在我有以下逻辑(简化的c ++伪代码):
// handles one connection
class Client
{
public:
void start(); //opens socket, connects, starts threads
void stop(); //closes socket, joins threads
ClientState getState();
void requestState();
private:
thread _threadReceive; // runs "handleReceive()" in a loop
thread _threadSend; // runs "handleSend()" in a loop
thread _threadUpdate; // runs "update()" in a loop
queue _commands;
queue _replies;
ClientState _currentState;
void handleReceive(); // recv reply from server, push to "_replies"
void handleSend(); // pops from "_commands", send to server
void update(); // pops reply, processes it, updates current state
//...
};
然后我有以下内容:
//App's logic
class App
{
public:
void start(); // init app, creates clients from config
void stop(); // iterates over "_clients" and calls "stop()", joins threads
private:
vector<Client> _clients;
vector<ClientState> _clientStates;
thread _threadUpdateClients;
thread _threadRequestClients;
void connect(); //iterate over "_clients" and "start()";
void updateStates(); //iterate over "_clients" and fill "_clientStates" accordingly
void requestStates(); //iterate over "_clients" and call "requestState()"
void updateUi(); // iterate over "_clientStates" and display them
//...
}
显然,这意味着有很多锁定和各种丑陋的代码来同步所有内容(这会导致上下文切换)。最令人沮丧的部分是它的工作原理,它在一个成功的应用程序中成长。
这段代码是几年前我写的.NET 4.5 C#代码(这是我的第一个实际的多线程应用程序。)的直接端口 - 我需要在几台Windows 2000和XP SP1机器上执行它。 我“感觉到”所有问题,但我不知道如何以适当的方式实现它。有很多简单的客户端 - 服务器教程,但我从来没有发现任何关于模式/架构,程序结构的东西。我也阅读了很多关于select()和非阻塞套接字的内容,但我真的很困惑:
我读到了asio,libev实现,但是他们隐藏了细节,最终我缺乏知识正是让我陷入这种境地的原因。 现在我只是迭代并更新所有活动连接,收集数据和显示,但我总觉得这不是一个正确的实现。
答案 0 :(得分:0)
你可以通过两个线程来实现,一个是UI线程,一个是网络线程,在网络线程中,你可以使用asio或libev。数据可以通过队列或共享变量传递。并使用条件变量或互斥来同步线程。你可以参考pthread库和man select函数。