網(wǎng)站怎么做才能用手機打開網(wǎng)頁在線代理翻墻
day16-重構(gòu)核心庫、使用智能指針(3)
最后將使用這個庫的方式進行展示。
1、客戶端
在while ((o = getopt(argc, argv, optstring)) != -1)所有的操作都是獲取參數(shù)的操作,threads 、msgs 和wait 分別指線程數(shù)、消息長度以及等待時間。
創(chuàng)建一個長度為threads的線程池,綁定任務(wù)(這種方式常用于回調(diào)函數(shù)的綁定,可以將某個函數(shù)與特定的參數(shù)值綁定,形成一個新的函數(shù)對象,方便在后續(xù)使用),將任務(wù)不斷加入線程池中進行處理。
int main(int argc, char *argv[]) {int threads = 100;int msgs = 100;int wait = 0;int o = -1;const char *optstring = "t:m:w:";while ((o = getopt(argc, argv, optstring)) != -1) {switch (o) {case 't':threads = std::stoi(optarg);break;case 'm':msgs = std::stoi(optarg);break;case 'w':wait = std::stoi(optarg);break;case '?':printf("error optopt: %c\n", optopt);printf("error opterr: %d\n", opterr);break;default:break;}}ThreadPool *poll = new ThreadPool(threads);std::function<void()> func = std::bind(OneClient, msgs, wait);for (int i = 0; i < threads; ++i) {poll->Add(func);}delete poll;return 0;
}
OneClient作為任務(wù)函數(shù)創(chuàng)建了一個socket作為客戶端并與服務(wù)器進行連接,將連接中的讀/寫緩存進行初始化并新建連接,開始不斷從內(nèi)核進行寫讀。
void OneClient(int msgs, int wait) {Socket *sock = new Socket();sock->Create();sock->Connect("127.0.0.1", 1234);Connection *conn = new Connection(sock->fd(), nullptr);sleep(wait);int count = 0;while (count < msgs) {conn->set_send_buf("I'm client!");conn->Write();if (conn->state() == Connection::State::Closed) {conn->Close();break;}conn->Read();std::cout << "msg count " << count++ << ": " << conn->read_buf()->c_str() << std::endl;}delete sock;delete conn;
}
2、服務(wù)器
首先創(chuàng)建sever服務(wù)器,在這個過程中完成了MainReactor、創(chuàng)建socket、綁定、監(jiān)聽、創(chuàng)建一個線程池并創(chuàng)建多個子 Reactor 等一系列動作。
當程序接收到SIGINT信號時,即用戶按下Ctrl+C鍵時,會執(zhí)行所注冊的信號處理函數(shù)。在這個例子中,信號處理函數(shù)的作用是釋放服務(wù)器對象的內(nèi)存、輸出提示信息并正常退出程序。
設(shè)置連接發(fā)生時的回調(diào)函數(shù)以及接收數(shù)據(jù)的回調(diào)函數(shù)
int main() {TcpServer *server = new TcpServer();Signal::signal(SIGINT, [&] {delete server;std::cout << "\nServer exit!" << std::endl;exit(0);});server->onConnect([](Connection *conn) { std::cout << "New connection fd: " << conn->socket()->fd() << std::endl; });server->onRecv([](Connection *conn) {std::cout << "Message from client " << conn->read_buf()->c_str() << std::endl;conn->Send(conn->read_buf()->c_str());});server->Start();delete server;return 0;
}
主Reactor在主線程中運行,專門負責(zé)監(jiān)聽和分發(fā)新的連接請求,從而實現(xiàn)了整個服務(wù)器的高效事件處理。
當服務(wù)器啟動時:
1、主Reactor開始監(jiān)聽新的連接請求。
2、每當有新的連接到達時,主Reactor接受連接并將其分配給某個子Reactor。
3、子Reactor在自己的線程中運行,不斷地處理與該連接相關(guān)的讀寫事件。
4、由于所有的 Loop 方法都在獨立的線程中運行,因此它們可以并發(fā)地處理各自的事件,而不會互相阻塞。
子Reactor處理的事件在線程池的線程中,而主Reactor處理的事件在主線程中。各自會被EventLoop不斷輪詢,直到停止。