diff --git a/.vscode/settings.json b/.vscode/settings.json index 3a5c2c4..ddd7b70 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,8 +1,8 @@ { "files.autoSave": "onFocusChange", - "editor.fontSize": 14, - //"editor.fontFamily": "'Monaspace Krypton Light', 'Monaspace Krypton Light', 'Monaspace Krypton Light'", - "terminal.integrated.fontFamily": "monospace", + "editor.fontSize": 13, + "editor.fontFamily": "'Source Code Pro', 'Source Code Pro', 'Source Code Pro'", + "terminal.integrated.fontFamily": "Source Code Pro", "cmake.configureOnOpen": true, "cmake.debugConfig": { "console": "integratedTerminal", @@ -122,6 +122,11 @@ "valarray": "cpp", "charconv": "cpp", "compare": "cpp", - "format": "cpp" + "format": "cpp", + "bit": "cpp", + "clocale": "cpp", + "concepts": "cpp", + "source_location": "cpp", + "stop_token": "cpp" } } \ No newline at end of file diff --git a/ClientCore/CMakeLists.txt b/ClientCore/CMakeLists.txt index 3a629c5..729a97e 100644 --- a/ClientCore/CMakeLists.txt +++ b/ClientCore/CMakeLists.txt @@ -12,4 +12,4 @@ ClientCore.cxx ) add_library(ClientCore STATIC ${MSOURCES}) -target_link_libraries(ClientCore PRIVATE wx::base wx::core) \ No newline at end of file +target_link_libraries(ClientCore PRIVATE wx::base wx::core Protocol Util) \ No newline at end of file diff --git a/ClientCore/ClientCore.cxx b/ClientCore/ClientCore.cxx index f1c5c36..c30dcf6 100644 --- a/ClientCore/ClientCore.cxx +++ b/ClientCore/ClientCore.cxx @@ -1,4 +1,5 @@ #include "ClientCore.h" +#include ClientCore::ClientCore() { @@ -12,14 +13,14 @@ bool ClientCore::Connect(const wxString& host, uint16_t port) addr.Service(port); socket_->SetEventHandler(*this, wxID_ANY); - socket_->SetNotify(wxSOCKET_CONNECTION_FLAG | wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG); + socket_->SetNotify(wxSOCKET_INPUT | wxSOCKET_LOST_FLAG); socket_->Notify(true); + socket_->SetFlags(wxSOCKET_BLOCK); if (!socket_->Connect(addr)) { return false; } - - return false; + return true; } void ClientCore::Disconnect() @@ -38,11 +39,28 @@ bool ClientCore::AskDirectory(const wxString& id, const wxString& path, DirFileI void ClientCore::OnSocketEvent(wxSocketEvent& event) { + auto* sock = event.GetSocket(); switch (event.GetSocketEvent()) { case wxSOCKET_CONNECTION: { + wxLogMessage(_("Client connected.")); break; } case wxSOCKET_INPUT: { + sock->Read(buf_.data(), GBUFFER_SIZE); + auto size = sock->LastCount(); + if (size > 0) { + buffer_.Push(buf_.data(), size); + while (thRun_) { + auto* frame = Communicate::ParseBuffer(buffer_); + if (!frame) { + break; + } + UseFrame(frame); + delete frame; + } + } else { + wxLogError(_("Read error: %s"), sock->LastError()); + } break; } case wxSOCKET_LOST: { @@ -52,3 +70,43 @@ void ClientCore::OnSocketEvent(wxSocketEvent& event) break; } } + +void ClientCore::UseFrame(FrameBuffer* buf) +{ + std::stringstream ss; + switch (buf->dataType) { + case FRAME_TYPE_INFO_CLIENT: { + InfoClientVec vec; + ZeroCopyInput input(buf->dataMut, buf->len); + input.archive() >> vec; + break; + } + default: + break; + } +} + +void ClientCore::HeartBeat() +{ +} + +bool ClientCore::Send(FrameBuffer* buf) +{ + if (buf == nullptr) { + return false; + } + char* od = nullptr; + int odLen = 0; + if (!Communicate::PackBuffer(buf, &od, odLen)) { + return false; + } + + socket_->Write(od, odLen); + if (socket_->Error()) { + delete[] od; + wxLogError(wxT("Send error: %s"), socket_->LastError()); + return false; + } + delete[] od; + return true; +} diff --git a/ClientCore/ClientCore.h b/ClientCore/ClientCore.h index 80e4466..6efdb3e 100644 --- a/ClientCore/ClientCore.h +++ b/ClientCore/ClientCore.h @@ -2,12 +2,17 @@ #define CLIENTCORE_H #include +#include #include +#include +#include #include #include #include #include +#include + class ClientCore : public wxEvtHandler { public: @@ -21,14 +26,33 @@ public: bool GetOnlineList(InfoClientVec& infoClientVec); bool AskDirectory(const wxString& id, const wxString& path, DirFileInfoVec& dirInfoVec); +private: + void UseFrame(FrameBuffer* buf); + private: void OnSocketEvent(wxSocketEvent& event); private: void HeartBeat(); + template bool Send(const T& info) + { + std::stringstream ss; + cereal::BinaryOutputArchive archive(ss); + archive(info); + + auto buf = std::make_shared(); + buf->dataConst = ss.view().data(); + buf->len = ss.str().size(); + + return Send(wxSock, buf.get()); + } + bool Send(FrameBuffer* buf); private: wxString id_; + bool thRun_; + MutBuffer buffer_; + std::array buf_; std::shared_ptr socket_; std::shared_ptr heartsThread_; }; diff --git a/Information/InfoCommunicate.hpp b/Information/InfoCommunicate.hpp index 34acfd3..9721314 100644 --- a/Information/InfoCommunicate.hpp +++ b/Information/InfoCommunicate.hpp @@ -6,9 +6,12 @@ #include #include +constexpr int GBUFFER_SIZE = 256; + enum MessageType { MSG_TYPE_ASK_CLIENTS = 1, - MSG_TYPE_FORWORD_FAILED + MSG_TYPE_FORWORD_FAILED, + MSG_TYPE_HEARTBEAT, }; struct InfoCommunicate { diff --git a/Information/InfoDirFile.hpp b/Information/InfoDirFile.hpp index 7ac97c9..2c4ef15 100644 --- a/Information/InfoDirFile.hpp +++ b/Information/InfoDirFile.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include @@ -17,25 +17,24 @@ enum FileType : uint32_t { }; struct DirFileInfo { + std::string name; + uint64_t size = 0; FileType type = None; std::string fullPath; - std::string name; - uint64_t lastModifyTime = 0; - uint64_t size = 0; uint16_t permission = 0; - + uint64_t lastModifyTime = 0; + DirFileInfo() = default; template void serialize(Archive& archive) { - archive(CEREAL_NVP(type), CEREAL_NVP(fullPath), CEREAL_NVP(name), CEREAL_NVP(lastModifyTime), CEREAL_NVP(size), - CEREAL_NVP(permission)); + archive(CEREAL_NVP(name), CEREAL_NVP(size), CEREAL_NVP(type), CEREAL_NVP(fullPath), CEREAL_NVP(permission), + CEREAL_NVP(lastModifyTime)); } }; struct DirFileInfoVec { std::vector vec; - template void serialize(Archive& archive) { archive(CEREAL_NVP(vec)); diff --git a/Information/InfoEnhance.hpp b/Information/InfoEnhance.hpp new file mode 100644 index 0000000..d72ff8c --- /dev/null +++ b/Information/InfoEnhance.hpp @@ -0,0 +1,34 @@ +#ifndef INFOENHANCE_HPP +#define INFOENHANCE_HPP + +#include +#include +#include + +class ZeroCopyInput +{ +public: + ZeroCopyInput(const char* data, size_t size) : streamBuf_(data, size), stream_(&streamBuf_) + { + } + + cereal::BinaryInputArchive archive() + { + return cereal::BinaryInputArchive(stream_); + } + +private: + class ConstStreamBuf : public std::streambuf + { + public: + ConstStreamBuf(const char* data, size_t size) + { + setg(const_cast(data), const_cast(data), const_cast(data + size)); + } + }; + + ConstStreamBuf streamBuf_; + std::istream stream_; +}; + +#endif // INFOENHANCE_HPP \ No newline at end of file diff --git a/Protocol/Communicate.cxx b/Protocol/Communicate.cxx index 563fbc6..ec3fbb5 100644 --- a/Protocol/Communicate.cxx +++ b/Protocol/Communicate.cxx @@ -9,13 +9,13 @@ Communicate::Communicate() /* 【 transm TCP 数据协议 】 - header 2 char: 0xFF 0xFE - unpack 1 char; - from 32 char: - to 32 char: - len 4 char: - data xxxxx: - tail 2 char: 0xFF 0xFF + header 2 char: 0xFF 0xFE + dataType 2 char; + from 32 char: + to 32 char: + len 4 char: + data xxxxx: + tail 2 char: 0xFF 0xFF */ FrameBuffer* Communicate::ParseBuffer(MutBuffer& buffer) { @@ -27,26 +27,26 @@ FrameBuffer* Communicate::ParseBuffer(MutBuffer& buffer) } int len = 0; - std::memcpy(&len, buffer.GetData() + find + sizeof(gHeader) + sizeof(uint8_t) + 64, sizeof(len)); - if (buffer.Length() < (find + sizeof(gHeader) + sizeof(uint8_t) + 64 + len + sizeof(len) + sizeof(gTail)) || len < 0) { + std::memcpy(&len, buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t) + 64, sizeof(len)); + if (buffer.Length() < (find + sizeof(gHeader) + sizeof(uint16_t) + 64 + len + sizeof(len) + sizeof(gTail)) || len < 0) { return frame; } - if (std::memcmp(buffer.GetData() + find + sizeof(gHeader) + sizeof(uint8_t) + 64 + sizeof(len) + len, gTail, sizeof(gTail)) != - 0) { + if (std::memcmp(buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t) + 64 + sizeof(len) + len, gTail, + sizeof(gTail)) != 0) { return frame; } frame = new FrameBuffer(); - frame->fid = std::string(buffer.GetData() + find + sizeof(gHeader) + sizeof(uint8_t), 32); - frame->tid = std::string(buffer.GetData() + find + sizeof(gHeader) + sizeof(uint8_t) + 32, 32); + frame->fid = std::string(buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t), 32); + frame->tid = std::string(buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t) + 32, 32); if (len > 0) { frame->dataMut = new char[len]; - std::memcpy(frame->dataMut, buffer.GetData() + find + sizeof(gHeader) + sizeof(uint8_t) + 64 + sizeof(len), len); + std::memcpy(frame->dataMut, buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t) + 64 + sizeof(len), len); frame->len = len; } - buffer.RemoveOf(0, find + sizeof(gHeader) + sizeof(uint8_t) + 64 + len + sizeof(len) + sizeof(gTail)); + buffer.RemoveOf(0, find + sizeof(gHeader) + sizeof(uint16_t) + 64 + len + sizeof(len) + sizeof(gTail)); return frame; } @@ -64,13 +64,13 @@ bool Communicate::PackBuffer(FrameBuffer* frame, char** buf, int& len) } else { dataPtr = frame->dataMut; } - len = sizeof(gHeader) + sizeof(uint8_t) + 64 + sizeof(len) + frame->len + sizeof(gTail); + len = sizeof(gHeader) + sizeof(uint16_t) + 64 + sizeof(len) + frame->len + sizeof(gTail); *buf = new char[len]; std::memcpy(*buf, gHeader, sizeof(gHeader)); - std::memcpy(*buf + sizeof(gHeader), &frame->unpack, sizeof(uint8_t)); - std::memcpy(*buf + sizeof(gHeader) + sizeof(uint8_t), frame->fid.c_str(), 32); - std::memcpy(*buf + sizeof(gHeader) + sizeof(uint8_t) + 32, frame->tid.c_str(), 32); - std::memcpy(*buf + sizeof(gHeader) + sizeof(uint8_t) + 64, &frame->len, sizeof(len)); + std::memcpy(*buf + sizeof(gHeader), &frame->dataType, sizeof(uint16_t)); + std::memcpy(*buf + sizeof(gHeader) + sizeof(uint16_t), frame->fid.c_str(), 32); + std::memcpy(*buf + sizeof(gHeader) + sizeof(uint16_t) + 32, frame->tid.c_str(), 32); + std::memcpy(*buf + sizeof(gHeader) + sizeof(uint16_t) + 64, &frame->len, sizeof(len)); if (frame->len > 0) { std::memcpy(*buf + sizeof(gHeader) + 64 + sizeof(len), dataPtr, frame->len); } diff --git a/Protocol/Communicate.h b/Protocol/Communicate.h index 62480a4..628c007 100644 --- a/Protocol/Communicate.h +++ b/Protocol/Communicate.h @@ -4,15 +4,24 @@ #include #include +enum FrameBufferType : uint16_t { + FRAME_TYPE_MSG_FILEDATA, + FRAME_TYPE_INFO_COMMUNICATE, + FRAME_TYPE_INFO_CLIENT, + FRAME_TYPE_INFO_DIRFILE, + FRAME_TYPE_MSG_YOURID +}; + struct FrameBuffer { FrameBuffer(); ~FrameBuffer(); - uint8_t unpack{}; + + int len{}; + char* dataMut; std::string fid; std::string tid; const char* dataConst; - char* dataMut; - int len{}; + FrameBufferType dataType{}; }; class Communicate diff --git a/RelayServer/RelayServer.cxx b/RelayServer/RelayServer.cxx index b1d956c..9544687 100644 --- a/RelayServer/RelayServer.cxx +++ b/RelayServer/RelayServer.cxx @@ -29,7 +29,7 @@ bool RemoteServer::Init(const wxString& ip, unsigned short port) // wxLogInfo(wxT("Server socket created on %s:%d"), addr.IPAddress(), addr.Service()); serverId_ = wxNewId(); - server_->SetFlags(wxSOCKET_WAITALL); + //server_->SetFlags(wxSOCKET_NOWAIT); server_->SetEventHandler(*this, serverId_); server_->SetNotify(wxSOCKET_CONNECTION_FLAG | wxSOCKET_LOST_FLAG); @@ -100,9 +100,10 @@ void RemoteServer::thClientThread(const std::shared_ptr& wxSock, c client = clients_[id]; } + client->wxSock->SetFlags(wxSOCKET_BLOCK); InfoCommunicate info; while (thRun_) { - wxSock->Read(client->buf.data(), gBufferSize); + wxSock->Read(client->buf.data(), GBUFFER_SIZE); auto br = wxSock->LastCount(); if (br == 0) { wxLogMessage(wxT("Client disconnected: %s"), id); @@ -117,7 +118,7 @@ void RemoteServer::thClientThread(const std::shared_ptr& wxSock, c if (!frame) { break; } - if (frame->unpack != 0) { + if (frame->dataType != 0) { std::stringstream ss; ss.write(frame->dataMut, frame->len); cereal::BinaryInputArchive inputArchive(ss); diff --git a/RelayServer/RelayServer.h b/RelayServer/RelayServer.h index 35a2cc9..920074d 100644 --- a/RelayServer/RelayServer.h +++ b/RelayServer/RelayServer.h @@ -17,8 +17,6 @@ #include #include -// constexpr int gBufferSize = 1024 * 1024; -constexpr int gBufferSize = 256; using highClock_t = std::chrono::time_point; using sockPtr = std::shared_ptr; struct TranClient { @@ -27,7 +25,7 @@ struct TranClient { int64_t onlineTime; std::string name; highClock_t lastRecvTime; - std::array buf; + std::array buf; }; class RemoteServer : public wxEvtHandler