add:添加一个处理新客户端线程。
This commit is contained in:
parent
595a2c9761
commit
31ae9aad2c
@ -11,7 +11,7 @@ ReflowComments: true
|
||||
SpacesBeforeTrailingComments: 3
|
||||
TabWidth: 4
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ColumnLimit: 80
|
||||
ColumnLimit: 130
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortEnumsOnASingleLine: false
|
||||
|
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@ -93,6 +93,9 @@
|
||||
"xmemory": "cpp",
|
||||
"xstring": "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(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin/${CMAKE_BUILD_TYPE}/)
|
||||
|
||||
add_subdirectory(util)
|
||||
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})
|
||||
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})
|
@ -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<wxSocketBase> 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<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
|
||||
#define SERVER_CORE_H
|
||||
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <gutil.h>
|
||||
#include <memory>
|
||||
#include <wx/wx.h>
|
||||
#include <wx/socket.h>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <wx/event.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
|
||||
{
|
||||
@ -19,10 +35,15 @@ public:
|
||||
|
||||
private:
|
||||
void OnServerEvent(wxSocketEvent& event);
|
||||
void th_client_thread(const std::shared_ptr<wxSocketBase>& socket, const wxString& id);
|
||||
|
||||
private:
|
||||
std::unique_ptr<wxSocketServer> server_{};
|
||||
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
|
@ -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