add:添加一个处理新客户端线程。

This commit is contained in:
taynpg 2025-03-31 22:51:47 +08:00
parent 595a2c9761
commit 31ae9aad2c
14 changed files with 199 additions and 39 deletions

View File

@ -11,7 +11,7 @@ ReflowComments: true
SpacesBeforeTrailingComments: 3 SpacesBeforeTrailingComments: 3
TabWidth: 4 TabWidth: 4
ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerAllOnOneLineOrOnePerLine: true
ColumnLimit: 80 ColumnLimit: 130
AllowShortBlocksOnASingleLine: Never AllowShortBlocksOnASingleLine: Never
AllowShortFunctionsOnASingleLine: None AllowShortFunctionsOnASingleLine: None
AllowShortEnumsOnASingleLine: false AllowShortEnumsOnASingleLine: false

View File

@ -93,6 +93,9 @@
"xmemory": "cpp", "xmemory": "cpp",
"xstring": "cpp", "xstring": "cpp",
"xtr1common": "cpp", "xtr1common": "cpp",
"xutility": "cpp" "xutility": "cpp",
"mutex": "cpp",
"array": "cpp",
"chrono": "cpp"
} }
} }

View File

@ -15,5 +15,6 @@ message(STATUS "Compiler CXX ID: ${CMAKE_CXX_COMPILER_ID}")
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib/${CMAKE_BUILD_TYPE}) set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib/${CMAKE_BUILD_TYPE})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin/${CMAKE_BUILD_TYPE}/) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin/${CMAKE_BUILD_TYPE}/)
add_subdirectory(util)
add_subdirectory(server-core) add_subdirectory(server-core)
add_subdirectory(example) add_subdirectory(server)

View File

@ -1,11 +0,0 @@
cmake_minimum_required(VERSION 3.16)
project(example LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(wxWidgets CONFIG REQUIRED)
add_executable(server-core-use server-core-use.cxx)
target_link_libraries(server-core-use PRIVATE server-core wx::net)
set_target_properties(server-core-use PROPERTIES WIN32_EXECUTABLE TRUE)

View File

@ -1,18 +0,0 @@
#include <server-core.h>
#include <iostream>
class ConsoleApp : public wxApp
{
public:
bool OnInit() override;
};
bool ConsoleApp::OnInit()
{
CServerCore server;
server.Init("127.0.0.1", 9897);
server.Run();
return false;
}
wxIMPLEMENT_APP(ConsoleApp);

View File

@ -12,5 +12,5 @@ server-core.cxx
) )
add_library(server-core STATIC ${PSOURCES}) add_library(server-core STATIC ${PSOURCES})
target_link_libraries(server-core PRIVATE wx::net wx::core) target_link_libraries(server-core PRIVATE wx::net wx::core gutil)
target_include_directories(server-core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(server-core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

View File

@ -38,11 +38,46 @@ int CServerCore::Run()
void CServerCore::OnServerEvent(wxSocketEvent& event) void CServerCore::OnServerEvent(wxSocketEvent& event)
{ {
if (event.GetSocketEvent() == wxSOCKET_CONNECTION) { if (event.GetSocketEvent() == wxSOCKET_CONNECTION) {
auto* cli = server_->Accept(); auto* cli_ptr = server_->Accept(true);
if (!cli) { if (!cli_ptr) {
return; return;
} }
wxString tmp("Nihao"); std::shared_ptr<wxSocketBase> cli(cli_ptr, [](wxSocketBase* ptr) { ptr->Destroy(); });
cli->Write(tmp.c_str(), tmp.size()); wxIPV4address peer_addr;
wxString id;
if (cli->GetPeer(peer_addr)) {
id.append(peer_addr.IPAddress());
id.append(":");
id.append(std::to_string(peer_addr.Service()));
wxLogMessage("New connection from %s", id);
}
bool can = false;
{
std::unique_lock<std::shared_mutex> lock(cli_mut_);
if (client_cache_.size() >= 100) {
can = false;
cli->Close();
} else {
auto cache = std::make_shared<ClientCache>();
cache->socket = cli;
cache->last_recv_time = std::chrono::high_resolution_clock::now();
auto now = wxDateTime::Now();
cache->online_time = wxString::Format("%s.%03ld", now.Format("%Y-%m-%d %H:%M:%S"), now.GetMillisecond());
client_cache_.emplace(id, cache);
can = true;
}
}
if (!can) {
std::this_thread::sleep_for(std::chrono::minutes(1));
} else {
client_thread_.emplace(id, std::thread(&CServerCore::th_client_thread, this, cli, id));
}
} }
} }
void CServerCore::th_client_thread(const std::shared_ptr<wxSocketBase>& socket, const wxString& id)
{
}

View File

@ -1,11 +1,27 @@
#ifndef SERVER_CORE_H #ifndef SERVER_CORE_H
#define SERVER_CORE_H #define SERVER_CORE_H
#include <array>
#include <chrono>
#include <gutil.h>
#include <memory> #include <memory>
#include <wx/wx.h> #include <mutex>
#include <wx/socket.h> #include <shared_mutex>
#include <thread>
#include <unordered_map>
#include <wx/event.h> #include <wx/event.h>
#include <wx/evtloop.h> #include <wx/evtloop.h>
#include <wx/socket.h>
#include <wx/wx.h>
using high_clock = std::chrono::time_point<std::chrono::high_resolution_clock>;
struct ClientCache {
std::shared_ptr<wxSocketBase> socket{};
CMutBuffer buffer{};
std::array<char, MAX_BUFFER_SIZE> recv_buffer{};
wxString online_time;
high_clock last_recv_time{};
};
class CServerCore : public wxEvtHandler class CServerCore : public wxEvtHandler
{ {
@ -19,10 +35,15 @@ public:
private: private:
void OnServerEvent(wxSocketEvent& event); void OnServerEvent(wxSocketEvent& event);
void th_client_thread(const std::shared_ptr<wxSocketBase>& socket, const wxString& id);
private: private:
std::unique_ptr<wxSocketServer> server_{}; std::unique_ptr<wxSocketServer> server_{};
wxWindowID server_id_{}; wxWindowID server_id_{};
std::unordered_map<wxString, std::shared_ptr<ClientCache>> client_cache_{};
std::unordered_map<wxString, std::thread> client_thread_{};
std::shared_mutex cli_mut_;
wxString server_ip_;
}; };
#endif #endif

View File

@ -0,0 +1,16 @@
cmake_minimum_required(VERSION 3.16)
project(server LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(wxWidgets CONFIG REQUIRED)
set(PSOURCES
server.cxx
server.h
)
add_executable(server ${PSOURCES})
target_link_libraries(server PRIVATE server-core wx::net gutil)
set_target_properties(server PROPERTIES WIN32_EXECUTABLE TRUE)

View File

@ -0,0 +1,11 @@
#include "server.h"
bool CServer::OnInit()
{
server_core_ = std::make_unique<CServerCore>();
server_core_->Init("127.0.0.1", 8080);
server_core_->Run();
return true;
}
wxIMPLEMENT_APP(CServer);

View File

@ -0,0 +1,16 @@
#ifndef SERVER_H
#define SERVER_H
#include <server-core.h>
#include <memory>
class CServer : public wxApp
{
public:
bool OnInit() override;
private:
std::unique_ptr<CServerCore> server_core_;
};
#endif

View File

@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.16)
project(gutil LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(PSOURCES
gutil.h
gutil.cxx
)
add_library(gutil STATIC ${PSOURCES})
target_include_directories(gutil PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

View File

@ -0,0 +1,47 @@
#include "gutil.h"
#include <algorithm>
#ifdef min
#undef min
#endif
void CMutBuffer::push(const char* data, int len)
{
buffer_.insert(buffer_.end(), data, data + len);
}
int CMutBuffer::index_of(const char* data, int len, int start_pos)
{
if (start_pos < 0 || start_pos >= static_cast<int>(buffer_.size()) || len <= 0) {
return -1;
}
auto it = std::search(buffer_.begin() + start_pos, buffer_.end(), data, data + len);
if (it != buffer_.end()) {
return std::distance(buffer_.begin(), it);
}
return -1;
}
const char* CMutBuffer::get_data() const
{
return buffer_.data();
}
int CMutBuffer::get_len() const
{
return static_cast<int>(buffer_.size());
}
void CMutBuffer::remove_of(int start_pos, int len)
{
if (start_pos < 0 || start_pos >= static_cast<int>(buffer_.size()) || len <= 0) {
return;
}
auto end_pos = std::min(start_pos + len, static_cast<int>(buffer_.size()));
buffer_.erase(buffer_.begin() + start_pos, buffer_.begin() + end_pos);
}
void CMutBuffer::clear()
{
buffer_.clear();
}

View File

@ -0,0 +1,26 @@
#ifndef GUTIL_H
#define GUTIL_H
#include <mutex>
#include <vector>
constexpr int MAX_BUFFER_SIZE = 1024 * 1024 * 10;
class CMutBuffer
{
public:
CMutBuffer() = default;
public:
void push(const char* data, int len);
int index_of(const char* data, int len, int start_pos = 0);
const char* get_data() const;
int get_len() const;
void remove_of(int start_pos, int len);
void clear();
private:
std::vector<char> buffer_;
};
#endif // GUTIL_H