diff --git a/.clang-format b/.clang-format index 402f22e..36e4997 100644 --- a/.clang-format +++ b/.clang-format @@ -11,7 +11,7 @@ ReflowComments: true SpacesBeforeTrailingComments: 3 TabWidth: 4 ConstructorInitializerAllOnOneLineOrOnePerLine: true -ColumnLimit: 80 +ColumnLimit: 130 AllowShortBlocksOnASingleLine: Never AllowShortFunctionsOnASingleLine: None AllowShortEnumsOnASingleLine: false diff --git a/.vscode/settings.json b/.vscode/settings.json index 751d02a..92d0128 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -93,6 +93,9 @@ "xmemory": "cpp", "xstring": "cpp", "xtr1common": "cpp", - "xutility": "cpp" + "xutility": "cpp", + "mutex": "cpp", + "array": "cpp", + "chrono": "cpp" } } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f88dd9..75fa448 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin/${CMAKE_BUILD_TYPE}/) +add_subdirectory(util) add_subdirectory(server-core) -add_subdirectory(example) \ No newline at end of file +add_subdirectory(server) \ No newline at end of file diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt deleted file mode 100644 index 1b793b3..0000000 --- a/example/CMakeLists.txt +++ /dev/null @@ -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) \ No newline at end of file diff --git a/example/server-core-use.cxx b/example/server-core-use.cxx deleted file mode 100644 index 24e41cf..0000000 --- a/example/server-core-use.cxx +++ /dev/null @@ -1,18 +0,0 @@ -#include -#include - -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); \ No newline at end of file diff --git a/server-core/CMakeLists.txt b/server-core/CMakeLists.txt index 0603dac..533d398 100644 --- a/server-core/CMakeLists.txt +++ b/server-core/CMakeLists.txt @@ -12,5 +12,5 @@ server-core.cxx ) 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}) \ No newline at end of file diff --git a/server-core/server-core.cxx b/server-core/server-core.cxx index 6a905a5..0fc41bf 100644 --- a/server-core/server-core.cxx +++ b/server-core/server-core.cxx @@ -38,11 +38,46 @@ int CServerCore::Run() void CServerCore::OnServerEvent(wxSocketEvent& event) { if (event.GetSocketEvent() == wxSOCKET_CONNECTION) { - auto* cli = server_->Accept(); - if (!cli) { + auto* cli_ptr = server_->Accept(true); + if (!cli_ptr) { return; } - wxString tmp("Nihao"); - cli->Write(tmp.c_str(), tmp.size()); + std::shared_ptr cli(cli_ptr, [](wxSocketBase* ptr) { ptr->Destroy(); }); + 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 lock(cli_mut_); + if (client_cache_.size() >= 100) { + can = false; + cli->Close(); + } else { + auto cache = std::make_shared(); + 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& socket, const wxString& id) +{ +} diff --git a/server-core/server-core.h b/server-core/server-core.h index 259e632..51e6ec3 100644 --- a/server-core/server-core.h +++ b/server-core/server-core.h @@ -1,11 +1,27 @@ #ifndef SERVER_CORE_H #define SERVER_CORE_H +#include +#include +#include #include -#include -#include +#include +#include +#include +#include #include #include +#include +#include + +using high_clock = std::chrono::time_point; +struct ClientCache { + std::shared_ptr socket{}; + CMutBuffer buffer{}; + std::array recv_buffer{}; + wxString online_time; + high_clock last_recv_time{}; +}; class CServerCore : public wxEvtHandler { @@ -19,10 +35,15 @@ public: private: void OnServerEvent(wxSocketEvent& event); + void th_client_thread(const std::shared_ptr& socket, const wxString& id); private: std::unique_ptr server_{}; wxWindowID server_id_{}; + std::unordered_map> client_cache_{}; + std::unordered_map client_thread_{}; + std::shared_mutex cli_mut_; + wxString server_ip_; }; #endif \ No newline at end of file diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index e69de29..86a4217 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -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) \ No newline at end of file diff --git a/server/server.cxx b/server/server.cxx index e69de29..1c76c6b 100644 --- a/server/server.cxx +++ b/server/server.cxx @@ -0,0 +1,11 @@ +#include "server.h" + +bool CServer::OnInit() +{ + server_core_ = std::make_unique(); + server_core_->Init("127.0.0.1", 8080); + server_core_->Run(); + return true; +} + +wxIMPLEMENT_APP(CServer); \ No newline at end of file diff --git a/server/server.h b/server/server.h index e69de29..9d0de4d 100644 --- a/server/server.h +++ b/server/server.h @@ -0,0 +1,16 @@ +#ifndef SERVER_H +#define SERVER_H + +#include +#include + +class CServer : public wxApp +{ +public: + bool OnInit() override; + +private: + std::unique_ptr server_core_; +}; + +#endif \ No newline at end of file diff --git a/util/CMakeLists.txt b/util/CMakeLists.txt index e69de29..637db4a 100644 --- a/util/CMakeLists.txt +++ b/util/CMakeLists.txt @@ -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}) \ No newline at end of file diff --git a/util/gutil.cxx b/util/gutil.cxx index e69de29..72ab63b 100644 --- a/util/gutil.cxx +++ b/util/gutil.cxx @@ -0,0 +1,47 @@ +#include "gutil.h" +#include + +#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(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(buffer_.size()); +} + +void CMutBuffer::remove_of(int start_pos, int len) +{ + if (start_pos < 0 || start_pos >= static_cast(buffer_.size()) || len <= 0) { + return; + } + auto end_pos = std::min(start_pos + len, static_cast(buffer_.size())); + buffer_.erase(buffer_.begin() + start_pos, buffer_.begin() + end_pos); +} + +void CMutBuffer::clear() +{ + buffer_.clear(); +} diff --git a/util/gutil.h b/util/gutil.h index e69de29..e62c53e 100644 --- a/util/gutil.h +++ b/util/gutil.h @@ -0,0 +1,26 @@ +#ifndef GUTIL_H +#define GUTIL_H + +#include +#include + +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 buffer_; +}; + +#endif // GUTIL_H \ No newline at end of file