add:添加一个处理新客户端线程。
This commit is contained in:
parent
595a2c9761
commit
31ae9aad2c
@ -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
|
||||||
|
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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)
|
@ -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)
|
|
@ -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);
|
|
@ -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})
|
@ -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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
@ -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
|
@ -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)
|
@ -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);
|
@ -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
|
@ -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})
|
@ -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();
|
||||||
|
}
|
26
util/gutil.h
26
util/gutil.h
@ -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
|
Loading…
x
Reference in New Issue
Block a user