client:客户端进度更新。

This commit is contained in:
taynpg 2025-05-10 21:43:25 +08:00
parent 0ed55b478d
commit 113fbee659
11 changed files with 177 additions and 46 deletions

13
.vscode/settings.json vendored
View File

@ -1,8 +1,8 @@
{ {
"files.autoSave": "onFocusChange", "files.autoSave": "onFocusChange",
"editor.fontSize": 14, "editor.fontSize": 13,
//"editor.fontFamily": "'Monaspace Krypton Light', 'Monaspace Krypton Light', 'Monaspace Krypton Light'", "editor.fontFamily": "'Source Code Pro', 'Source Code Pro', 'Source Code Pro'",
"terminal.integrated.fontFamily": "monospace", "terminal.integrated.fontFamily": "Source Code Pro",
"cmake.configureOnOpen": true, "cmake.configureOnOpen": true,
"cmake.debugConfig": { "cmake.debugConfig": {
"console": "integratedTerminal", "console": "integratedTerminal",
@ -122,6 +122,11 @@
"valarray": "cpp", "valarray": "cpp",
"charconv": "cpp", "charconv": "cpp",
"compare": "cpp", "compare": "cpp",
"format": "cpp" "format": "cpp",
"bit": "cpp",
"clocale": "cpp",
"concepts": "cpp",
"source_location": "cpp",
"stop_token": "cpp"
} }
} }

View File

@ -12,4 +12,4 @@ ClientCore.cxx
) )
add_library(ClientCore STATIC ${MSOURCES}) add_library(ClientCore STATIC ${MSOURCES})
target_link_libraries(ClientCore PRIVATE wx::base wx::core) target_link_libraries(ClientCore PRIVATE wx::base wx::core Protocol Util)

View File

@ -1,4 +1,5 @@
#include "ClientCore.h" #include "ClientCore.h"
#include <InfoEnhance.hpp>
ClientCore::ClientCore() ClientCore::ClientCore()
{ {
@ -12,14 +13,14 @@ bool ClientCore::Connect(const wxString& host, uint16_t port)
addr.Service(port); addr.Service(port);
socket_->SetEventHandler(*this, wxID_ANY); 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_->Notify(true);
socket_->SetFlags(wxSOCKET_BLOCK);
if (!socket_->Connect(addr)) { if (!socket_->Connect(addr)) {
return false; return false;
} }
return true;
return false;
} }
void ClientCore::Disconnect() void ClientCore::Disconnect()
@ -38,11 +39,28 @@ bool ClientCore::AskDirectory(const wxString& id, const wxString& path, DirFileI
void ClientCore::OnSocketEvent(wxSocketEvent& event) void ClientCore::OnSocketEvent(wxSocketEvent& event)
{ {
auto* sock = event.GetSocket();
switch (event.GetSocketEvent()) { switch (event.GetSocketEvent()) {
case wxSOCKET_CONNECTION: { case wxSOCKET_CONNECTION: {
wxLogMessage(_("Client connected."));
break; break;
} }
case wxSOCKET_INPUT: { 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; break;
} }
case wxSOCKET_LOST: { case wxSOCKET_LOST: {
@ -52,3 +70,43 @@ void ClientCore::OnSocketEvent(wxSocketEvent& event)
break; 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;
}

View File

@ -2,12 +2,17 @@
#define CLIENTCORE_H #define CLIENTCORE_H
#include <InfoClient.hpp> #include <InfoClient.hpp>
#include <InfoCommunicate.hpp>
#include <InfoDirFile.hpp> #include <InfoDirFile.hpp>
#include <Communicate.h>
#include <array>
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <wx/socket.h> #include <wx/socket.h>
#include <Util.h>
class ClientCore : public wxEvtHandler class ClientCore : public wxEvtHandler
{ {
public: public:
@ -21,14 +26,33 @@ public:
bool GetOnlineList(InfoClientVec& infoClientVec); bool GetOnlineList(InfoClientVec& infoClientVec);
bool AskDirectory(const wxString& id, const wxString& path, DirFileInfoVec& dirInfoVec); bool AskDirectory(const wxString& id, const wxString& path, DirFileInfoVec& dirInfoVec);
private:
void UseFrame(FrameBuffer* buf);
private: private:
void OnSocketEvent(wxSocketEvent& event); void OnSocketEvent(wxSocketEvent& event);
private: private:
void HeartBeat(); void HeartBeat();
template <typename T> bool Send(const T& info)
{
std::stringstream ss;
cereal::BinaryOutputArchive archive(ss);
archive(info);
auto buf = std::make_shared<FrameBuffer>();
buf->dataConst = ss.view().data();
buf->len = ss.str().size();
return Send(wxSock, buf.get());
}
bool Send(FrameBuffer* buf);
private: private:
wxString id_; wxString id_;
bool thRun_;
MutBuffer buffer_;
std::array<char, GBUFFER_SIZE> buf_;
std::shared_ptr<wxSocketClient> socket_; std::shared_ptr<wxSocketClient> socket_;
std::shared_ptr<wxThread> heartsThread_; std::shared_ptr<wxThread> heartsThread_;
}; };

View File

@ -6,9 +6,12 @@
#include <cereal/types/vector.hpp> #include <cereal/types/vector.hpp>
#include <cstdint> #include <cstdint>
constexpr int GBUFFER_SIZE = 256;
enum MessageType { enum MessageType {
MSG_TYPE_ASK_CLIENTS = 1, MSG_TYPE_ASK_CLIENTS = 1,
MSG_TYPE_FORWORD_FAILED MSG_TYPE_FORWORD_FAILED,
MSG_TYPE_HEARTBEAT,
}; };
struct InfoCommunicate { struct InfoCommunicate {

View File

@ -17,25 +17,24 @@ enum FileType : uint32_t {
}; };
struct DirFileInfo { struct DirFileInfo {
std::string name;
uint64_t size = 0;
FileType type = None; FileType type = None;
std::string fullPath; std::string fullPath;
std::string name;
uint64_t lastModifyTime = 0;
uint64_t size = 0;
uint16_t permission = 0; uint16_t permission = 0;
uint64_t lastModifyTime = 0;
DirFileInfo() = default; DirFileInfo() = default;
template <class Archive> void serialize(Archive& archive) template <class Archive> void serialize(Archive& archive)
{ {
archive(CEREAL_NVP(type), CEREAL_NVP(fullPath), CEREAL_NVP(name), CEREAL_NVP(lastModifyTime), CEREAL_NVP(size), archive(CEREAL_NVP(name), CEREAL_NVP(size), CEREAL_NVP(type), CEREAL_NVP(fullPath), CEREAL_NVP(permission),
CEREAL_NVP(permission)); CEREAL_NVP(lastModifyTime));
} }
}; };
struct DirFileInfoVec { struct DirFileInfoVec {
std::vector<DirFileInfo> vec; std::vector<DirFileInfo> vec;
template <class Archive> void serialize(Archive& archive) template <class Archive> void serialize(Archive& archive)
{ {
archive(CEREAL_NVP(vec)); archive(CEREAL_NVP(vec));

View File

@ -0,0 +1,34 @@
#ifndef INFOENHANCE_HPP
#define INFOENHANCE_HPP
#include <cereal/archives/binary.hpp>
#include <cereal/types/memory.hpp>
#include <streambuf>
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<char*>(data), const_cast<char*>(data), const_cast<char*>(data + size));
}
};
ConstStreamBuf streamBuf_;
std::istream stream_;
};
#endif // INFOENHANCE_HPP

View File

@ -10,7 +10,7 @@ Communicate::Communicate()
/* /*
transm TCP transm TCP
header 2 char: 0xFF 0xFE header 2 char: 0xFF 0xFE
unpack 1 char; dataType 2 char;
from 32 char: from 32 char:
to 32 char: to 32 char:
len 4 char: len 4 char:
@ -27,26 +27,26 @@ FrameBuffer* Communicate::ParseBuffer(MutBuffer& buffer)
} }
int len = 0; int len = 0;
std::memcpy(&len, buffer.GetData() + find + sizeof(gHeader) + sizeof(uint8_t) + 64, sizeof(len)); std::memcpy(&len, buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t) + 64, sizeof(len));
if (buffer.Length() < (find + sizeof(gHeader) + sizeof(uint8_t) + 64 + len + sizeof(len) + sizeof(gTail)) || len < 0) { if (buffer.Length() < (find + sizeof(gHeader) + sizeof(uint16_t) + 64 + len + sizeof(len) + sizeof(gTail)) || len < 0) {
return frame; return frame;
} }
if (std::memcmp(buffer.GetData() + find + sizeof(gHeader) + sizeof(uint8_t) + 64 + sizeof(len) + len, gTail, sizeof(gTail)) != if (std::memcmp(buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t) + 64 + sizeof(len) + len, gTail,
0) { sizeof(gTail)) != 0) {
return frame; return frame;
} }
frame = new FrameBuffer(); frame = new FrameBuffer();
frame->fid = std::string(buffer.GetData() + find + sizeof(gHeader) + sizeof(uint8_t), 32); frame->fid = std::string(buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t), 32);
frame->tid = std::string(buffer.GetData() + find + sizeof(gHeader) + sizeof(uint8_t) + 32, 32); frame->tid = std::string(buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t) + 32, 32);
if (len > 0) { if (len > 0) {
frame->dataMut = new char[len]; 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; 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; return frame;
} }
@ -64,13 +64,13 @@ bool Communicate::PackBuffer(FrameBuffer* frame, char** buf, int& len)
} else { } else {
dataPtr = frame->dataMut; 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]; *buf = new char[len];
std::memcpy(*buf, gHeader, sizeof(gHeader)); std::memcpy(*buf, gHeader, sizeof(gHeader));
std::memcpy(*buf + sizeof(gHeader), &frame->unpack, sizeof(uint8_t)); std::memcpy(*buf + sizeof(gHeader), &frame->dataType, sizeof(uint16_t));
std::memcpy(*buf + sizeof(gHeader) + sizeof(uint8_t), frame->fid.c_str(), 32); std::memcpy(*buf + sizeof(gHeader) + sizeof(uint16_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(uint16_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) + sizeof(uint16_t) + 64, &frame->len, sizeof(len));
if (frame->len > 0) { if (frame->len > 0) {
std::memcpy(*buf + sizeof(gHeader) + 64 + sizeof(len), dataPtr, frame->len); std::memcpy(*buf + sizeof(gHeader) + 64 + sizeof(len), dataPtr, frame->len);
} }

View File

@ -4,15 +4,24 @@
#include <Util.h> #include <Util.h>
#include <cstdint> #include <cstdint>
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 { struct FrameBuffer {
FrameBuffer(); FrameBuffer();
~FrameBuffer(); ~FrameBuffer();
uint8_t unpack{};
int len{};
char* dataMut;
std::string fid; std::string fid;
std::string tid; std::string tid;
const char* dataConst; const char* dataConst;
char* dataMut; FrameBufferType dataType{};
int len{};
}; };
class Communicate class Communicate

View File

@ -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()); // wxLogInfo(wxT("Server socket created on %s:%d"), addr.IPAddress(), addr.Service());
serverId_ = wxNewId(); serverId_ = wxNewId();
server_->SetFlags(wxSOCKET_WAITALL); //server_->SetFlags(wxSOCKET_NOWAIT);
server_->SetEventHandler(*this, serverId_); server_->SetEventHandler(*this, serverId_);
server_->SetNotify(wxSOCKET_CONNECTION_FLAG | wxSOCKET_LOST_FLAG); server_->SetNotify(wxSOCKET_CONNECTION_FLAG | wxSOCKET_LOST_FLAG);
@ -100,9 +100,10 @@ void RemoteServer::thClientThread(const std::shared_ptr<wxSocketBase>& wxSock, c
client = clients_[id]; client = clients_[id];
} }
client->wxSock->SetFlags(wxSOCKET_BLOCK);
InfoCommunicate info; InfoCommunicate info;
while (thRun_) { while (thRun_) {
wxSock->Read(client->buf.data(), gBufferSize); wxSock->Read(client->buf.data(), GBUFFER_SIZE);
auto br = wxSock->LastCount(); auto br = wxSock->LastCount();
if (br == 0) { if (br == 0) {
wxLogMessage(wxT("Client disconnected: %s"), id); wxLogMessage(wxT("Client disconnected: %s"), id);
@ -117,7 +118,7 @@ void RemoteServer::thClientThread(const std::shared_ptr<wxSocketBase>& wxSock, c
if (!frame) { if (!frame) {
break; break;
} }
if (frame->unpack != 0) { if (frame->dataType != 0) {
std::stringstream ss; std::stringstream ss;
ss.write(frame->dataMut, frame->len); ss.write(frame->dataMut, frame->len);
cereal::BinaryInputArchive inputArchive(ss); cereal::BinaryInputArchive inputArchive(ss);

View File

@ -17,8 +17,6 @@
#include <wx/socket.h> #include <wx/socket.h>
#include <wx/wx.h> #include <wx/wx.h>
// constexpr int gBufferSize = 1024 * 1024;
constexpr int gBufferSize = 256;
using highClock_t = std::chrono::time_point<std::chrono::high_resolution_clock>; using highClock_t = std::chrono::time_point<std::chrono::high_resolution_clock>;
using sockPtr = std::shared_ptr<wxSocketBase>; using sockPtr = std::shared_ptr<wxSocketBase>;
struct TranClient { struct TranClient {
@ -27,7 +25,7 @@ struct TranClient {
int64_t onlineTime; int64_t onlineTime;
std::string name; std::string name;
highClock_t lastRecvTime; highClock_t lastRecvTime;
std::array<char, gBufferSize> buf; std::array<char, GBUFFER_SIZE> buf;
}; };
class RemoteServer : public wxEvtHandler class RemoteServer : public wxEvtHandler