client:客户端进度更新。
This commit is contained in:
parent
0ed55b478d
commit
113fbee659
13
.vscode/settings.json
vendored
13
.vscode/settings.json
vendored
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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)
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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_;
|
||||||
};
|
};
|
||||||
|
@ -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 {
|
||||||
|
@ -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));
|
||||||
|
34
Information/InfoEnhance.hpp
Normal file
34
Information/InfoEnhance.hpp
Normal 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
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
Reference in New Issue
Block a user