From 64c0637e6ac7dac9e5b219ede4c251d0ce7c6145 Mon Sep 17 00:00:00 2001 From: Sergey Sklyarov Date: Fri, 11 Apr 2025 14:56:04 +0300 Subject: [PATCH] cpp --- .gitignore | 3 +- DroneClientCpp/Client.cpp | 106 ++++++++++ DroneClientCpp/Client.h | 44 ++++ DroneClientCpp/Drone.cpp | 197 ++++++++++++++++++ DroneClientCpp/Drone.h | 46 ++++ DroneClientCpp/DroneClient.h | 65 ++++++ DroneClientCpp/DroneClientCpp.sln | 28 +++ DroneClientCpp/DroneClientCpp.vcxproj | 141 +++++++++++++ DroneClientCpp/DroneClientCpp.vcxproj.filters | 42 ++++ DroneClientCpp/DroneClientCpp.vcxproj.user | 4 + DroneClientCpp/DroneData.h | 77 +++++++ DroneClientCpp/FormMain.cpp | 12 ++ DroneClientCpp/FormMain.h | Bin 0 -> 75238 bytes DroneClientCpp/FormMain.resx | 126 +++++++++++ DroneClientCpp/MyForm.cpp | 12 ++ DroneClientCpp/MyForm.h | Bin 0 -> 4284 bytes DroneClientCpp/MyForm.resx | 120 +++++++++++ DroneClientCpp/NetClient.cpp | 105 ++++++++++ DroneClientCpp/NetClient.h | 68 ++++++ DroneClientCpp/Source.cpp | 11 + 20 files changed, 1206 insertions(+), 1 deletion(-) create mode 100644 DroneClientCpp/Client.cpp create mode 100644 DroneClientCpp/Client.h create mode 100644 DroneClientCpp/Drone.cpp create mode 100644 DroneClientCpp/Drone.h create mode 100644 DroneClientCpp/DroneClient.h create mode 100644 DroneClientCpp/DroneClientCpp.sln create mode 100644 DroneClientCpp/DroneClientCpp.vcxproj create mode 100644 DroneClientCpp/DroneClientCpp.vcxproj.filters create mode 100644 DroneClientCpp/DroneClientCpp.vcxproj.user create mode 100644 DroneClientCpp/DroneData.h create mode 100644 DroneClientCpp/FormMain.cpp create mode 100644 DroneClientCpp/FormMain.h create mode 100644 DroneClientCpp/FormMain.resx create mode 100644 DroneClientCpp/MyForm.cpp create mode 100644 DroneClientCpp/MyForm.h create mode 100644 DroneClientCpp/MyForm.resx create mode 100644 DroneClientCpp/NetClient.cpp create mode 100644 DroneClientCpp/NetClient.h create mode 100644 DroneClientCpp/Source.cpp diff --git a/.gitignore b/.gitignore index 98d63b2..a4574de 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .vs/ obj/ -bin/ \ No newline at end of file +bin/ +x64/ \ No newline at end of file diff --git a/DroneClientCpp/Client.cpp b/DroneClientCpp/Client.cpp new file mode 100644 index 0000000..7fab2d4 --- /dev/null +++ b/DroneClientCpp/Client.cpp @@ -0,0 +1,106 @@ +#pragma once + +#include "Client.h" + +Client::Client(const char* ip, int port) : running(true), Connection(INVALID_SOCKET) +{ + if (!ConnectToServer(ip, port)) + { + std::cerr << "Failed to connect to server!" << std::endl; + } +} + +Client::~Client() +{ + Stop(); + CloseConnection(); +} + +bool Client::ConnectToServer(const char* ip, int port) +{ + WSAData wsaData; + WORD DLLVersion = MAKEWORD(2, 2); + + if (WSAStartup(DLLVersion, &wsaData) != 0) + { + std::cerr << "Error: WSAStartup failed" << std::endl; + return false; + } + + SOCKADDR_IN addr; + inet_pton(AF_INET, ip, &addr.sin_addr); + addr.sin_port = htons(port); + addr.sin_family = AF_INET; + + Connection = socket(AF_INET, SOCK_STREAM, 0); + if (Connection == INVALID_SOCKET) + { + std::cerr << "Error: Failed to create socket" << std::endl; + WSACleanup(); + return false; + } + + if (connect(Connection, (SOCKADDR*)&addr, sizeof(addr)) != 0) + { + std::cerr << "Error: Failed to connect to server" << std::endl; + closesocket(Connection); + WSACleanup(); + return false; + } + + return true; +} + +void Client::CloseConnection() +{ + if (Connection != INVALID_SOCKET) + { + closesocket(Connection); + WSACleanup(); + Connection = INVALID_SOCKET; + } +} + +void Client::ReceiveHandler() +{ + while (running) + { + DataIn tempData; + int result = recv(Connection, (char*)&tempData, sizeof(tempData), 0); + + if (result <= 0) + { + std::cerr << "Error: Connection lost (recv failed)" << std::endl; + running = false; + break; + } + + std::lock_guard lock(dataMutex); + dataIn = tempData; + } +} + +void Client::SendHandler() +{ + while (running) + { + { + std::lock_guard lock(dataMutex); + send(Connection, (char*)&dataOut, sizeof(dataOut), 0); + } + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } +} + +void Client::Start() +{ + recvThread = std::thread(&Client::ReceiveHandler, this); + sendThread = std::thread(&Client::SendHandler, this); +} + +void Client::Stop() +{ + running = false; + if (recvThread.joinable()) recvThread.join(); + if (sendThread.joinable()) sendThread.join(); +} diff --git a/DroneClientCpp/Client.h b/DroneClientCpp/Client.h new file mode 100644 index 0000000..6801903 --- /dev/null +++ b/DroneClientCpp/Client.h @@ -0,0 +1,44 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#pragma comment(lib, "Ws2_32.lib") + +class Client +{ +public: + Client(const char* ip, int port); + ~Client(); + + void Start(); // Запуск потоков + void Stop(); // Остановка потоков + struct DataIn + { + float AccX, AccY, AccZ; + float GyrX, GyrY, GyrZ; + float PosX, PosY, LaserRange; + } dataIn; + + struct DataOut + { + float MotorUL, MotorUR, MotorDL, MotorDR; + } dataOut; + bool ConnectToServer(const char* ip, int port); + void CloseConnection(); + +private: + std::atomic running; + std::mutex dataMutex; + + SOCKET Connection; + std::thread recvThread; + std::thread sendThread; + + void ReceiveHandler(); + void SendHandler(); +}; \ No newline at end of file diff --git a/DroneClientCpp/Drone.cpp b/DroneClientCpp/Drone.cpp new file mode 100644 index 0000000..b59532a --- /dev/null +++ b/DroneClientCpp/Drone.cpp @@ -0,0 +1,197 @@ +#include "Drone.h" + +namespace DroneClient { + + // Реализация статического метода GetBytes + array^ Drone::GetBytes(Object^ data) + { + int size = Marshal::SizeOf(data); + array^ arr = gcnew array(size); + + IntPtr ptr = IntPtr::Zero; + try + { + ptr = Marshal::AllocHGlobal(size); + Marshal::StructureToPtr(data, ptr, true); + Marshal::Copy(ptr, arr, 0, size); + } + finally + { + Marshal::FreeHGlobal(ptr); + } + return arr; + } + + // Реализация статического метода FromBytes + Object^ Drone::FromBytes(array^ arr, Type^ type) + { + Object^ mem = gcnew Object(); + + int size = Marshal::SizeOf(type); + IntPtr ptr = IntPtr::Zero; + try + { + ptr = Marshal::AllocHGlobal(size); + Marshal::Copy(arr, 0, ptr, size); + mem = Marshal::PtrToStructure(ptr, type); + } + finally + { + Marshal::FreeHGlobal(ptr); + } + return mem; + } + + // Реализация приватного метода SendDataMotor4 + array^ Drone::SendDataMotor4() + { + DroneData::DataMotor4 mot4; + + mot4.Head.Size = Marshal::SizeOf(DroneData::DataMotor4::typeid); + mot4.Head.Mode = DroneData::DataMode::Response; + mot4.Head.Type = DroneData::DataType::DataMotor4; + + mot4.UL = MotorUL; + mot4.UR = MotorUR; + mot4.DL = MotorDL; + mot4.DR = MotorDR; + + return GetBytes(mot4); + } + + // Реализация приватного метода RecvDataIMU + array^ Drone::RecvDataIMU(array^ data) + { + DroneData::DataIMU imu = (DroneData::DataIMU)FromBytes(data, DroneData::DataIMU::typeid); + + AccX = imu.Acc.X; AccY = imu.Acc.Y; AccZ = imu.Acc.Z; + GyrX = imu.Gyr.X; GyrY = imu.Gyr.Y; GyrZ = imu.Gyr.Z; + + return gcnew array(0); + } + + // Реализация приватного метода RecvDataPos + array^ Drone::RecvDataPos(array^ data) + { + DroneData::DataPos pos = (DroneData::DataPos)FromBytes(data, DroneData::DataPos::typeid); + + PosX = pos.Local.X; PosY = pos.Local.Y; + LaserRange = pos.LiDAR; + + return gcnew array(0); + } + + // Реализация приватного метода ClientRequestResponse + array^ Drone::ClientRequestResponse(DroneData::DataHead head, array^ body) + { + array^ zero = gcnew array(0); + + switch (head.Type) + { + case DroneData::DataType::DataIMU: + if (head.Mode == DroneData::DataMode::Request) + { + return zero; // Запрос данных (не реализовано) + } + else + { + return RecvDataIMU(body); // Пришли данные + } + + case DroneData::DataType::DataPos: + if (head.Mode == DroneData::DataMode::Request) + { + return zero; // Запрос данных (не реализовано) + } + else + { + return RecvDataPos(body); // Пришли данные + } + + case DroneData::DataType::DataMotor4: + if (head.Mode == DroneData::DataMode::Request) + { + return SendDataMotor4(); // Запрос данных + } + else + { + return zero; // Пришли данные (не реализовано) + } + } + + return zero; + } + + // Реализация конструктора + Drone::Drone() + { + DroneStreamData = gcnew array(DroneStreamCount); // Инициализация массива + DroneStreamIndex = 0; + DroneStreamHead.Mode = DroneData::DataMode::None; + DroneStreamHead.Size = 0; + DroneStreamHead.Type = DroneData::DataType::None; + } + + // Реализация метода DataStream + System::Collections::Generic::List^>^ Drone::DataStream(array^ data, int size) + { + System::Collections::Generic::List^>^ ret = gcnew System::Collections::Generic::List^>(); + + if (data == nullptr) return ret; // Последовательность не сформирована + + if (size + DroneStreamIndex > DroneStreamCount) return nullptr; // Ошибка переполнения + + Array::Copy(data, 0, DroneStreamData, DroneStreamIndex, size); + DroneStreamIndex += size; + + while (true) + { + if (DroneStreamHead.Size == 0) // Заголовок еще не получен + { + if (DroneStreamIndex < DroneData::DataHead::StrLen) return ret; + DroneStreamHead = (DroneData::DataHead)FromBytes(DroneStreamData, DroneData::DataHead::typeid); + } + + if (DroneStreamHead.Size > DroneStreamIndex) break; // Пакет еще не полный + + array^ body = gcnew array(DroneStreamHead.Size); + Array::Copy(DroneStreamData, 0, body, 0, DroneStreamHead.Size); + + int shift = DroneStreamHead.Size; + + DroneStreamIndex -= shift; + Array::Copy(DroneStreamData, shift, DroneStreamData, 0, DroneStreamIndex); // Сдвиг массива + + DroneStreamHead.Size = 0; // Сброс заголовка + + ret->Add(ClientRequestResponse(DroneStreamHead, body)); + } + + return ret; + } + + // Реализация метода SendRequest + array^ Drone::SendRequest() + { + DroneData::DataHead imu; + imu.Size = DroneData::DataHead::StrLen; + imu.Mode = DroneData::DataMode::Request; + imu.Type = DroneData::DataType::DataIMU; + + DroneData::DataHead pos; + pos.Size = DroneData::DataHead::StrLen; + pos.Mode = DroneData::DataMode::Request; + pos.Type = DroneData::DataType::DataPos; + + array^ si = GetBytes(imu); + array^ sp = GetBytes(pos); + array^ sm = SendDataMotor4(); + + array^ send = gcnew array(si->Length + sp->Length + sm->Length); + Array::Copy(si, 0, send, 0, si->Length); + Array::Copy(sp, 0, send, si->Length, sp->Length); + Array::Copy(sm, 0, send, si->Length + sp->Length, sm->Length); + + return send; + } +} \ No newline at end of file diff --git a/DroneClientCpp/Drone.h b/DroneClientCpp/Drone.h new file mode 100644 index 0000000..2b603e7 --- /dev/null +++ b/DroneClientCpp/Drone.h @@ -0,0 +1,46 @@ +#pragma once + +#include "DroneData.h" +#include +#include + +#using +#using + +using namespace System; +using namespace System::Collections::Generic; +using namespace System::Runtime::InteropServices; + +namespace DroneClient { + + public ref class Drone + { + public: + float AccX, AccY, AccZ; + float GyrX, GyrY, GyrZ; + float PosX, PosY; + float LaserRange; + + float MotorUL, MotorUR, MotorDL, MotorDR; + + static array^ GetBytes(Object^ data); + static Object^ FromBytes(array^ arr, Type^ type); + + private: + array^ SendDataMotor4(); + array^ RecvDataIMU(array^ data); + array^ RecvDataPos(array^ data); + array^ ClientRequestResponse(DroneData::DataHead head, array^ body); + + literal int DroneStreamCount = 512; + array^ DroneStreamData; + int DroneStreamIndex; + DroneData::DataHead DroneStreamHead; + + public: + Drone(); // Конструктор для инициализации + + System::Collections::Generic::List^>^ DataStream(array^ data, int size); + array^ SendRequest(); + }; +} \ No newline at end of file diff --git a/DroneClientCpp/DroneClient.h b/DroneClientCpp/DroneClient.h new file mode 100644 index 0000000..56ff135 --- /dev/null +++ b/DroneClientCpp/DroneClient.h @@ -0,0 +1,65 @@ +#pragma once + +#include +#include + +#using +#using + +using namespace System; +using namespace System::Runtime::InteropServices; + +namespace DroneClient { + + public ref class Drone + { + public: + value struct DataOut + { + float AccX, AccY, AccZ; + float GyrX, GyrY, GyrZ; + float PosX, PosY; + float LaserRange; + }; + + value struct DataIn + { + float MotorUL, MotorUR, MotorDL, MotorDR; + }; + + static array^ GetBytes(Object^ data) + { + int size = Marshal::SizeOf(data); + array^ arr = gcnew array(size); + + IntPtr ptr = IntPtr::Zero; + try + { + ptr = Marshal::AllocHGlobal(size); + Marshal::StructureToPtr(data, ptr, true); + Marshal::Copy(ptr, arr, 0, size); + } + finally + { + Marshal::FreeHGlobal(ptr); + } + return arr; + } + + static Object^ FromBytes(array^ arr, Type^ type) + { + int size = Marshal::SizeOf(type); + IntPtr ptr = IntPtr::Zero; + try + { + ptr = Marshal::AllocHGlobal(size); + Marshal::Copy(arr, 0, ptr, size); + return Marshal::PtrToStructure(ptr, type); + } + finally + { + Marshal::FreeHGlobal(ptr); + } + } + }; +} \ No newline at end of file diff --git a/DroneClientCpp/DroneClientCpp.sln b/DroneClientCpp/DroneClientCpp.sln new file mode 100644 index 0000000..0272a0e --- /dev/null +++ b/DroneClientCpp/DroneClientCpp.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35527.113 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DroneClientCpp", "DroneClientCpp.vcxproj", "{690C304C-A70B-4B0F-BF61-8C51290BF444}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {690C304C-A70B-4B0F-BF61-8C51290BF444}.Debug|x64.ActiveCfg = Debug|x64 + {690C304C-A70B-4B0F-BF61-8C51290BF444}.Debug|x64.Build.0 = Debug|x64 + {690C304C-A70B-4B0F-BF61-8C51290BF444}.Debug|x86.ActiveCfg = Debug|Win32 + {690C304C-A70B-4B0F-BF61-8C51290BF444}.Debug|x86.Build.0 = Debug|Win32 + {690C304C-A70B-4B0F-BF61-8C51290BF444}.Release|x64.ActiveCfg = Release|x64 + {690C304C-A70B-4B0F-BF61-8C51290BF444}.Release|x64.Build.0 = Release|x64 + {690C304C-A70B-4B0F-BF61-8C51290BF444}.Release|x86.ActiveCfg = Release|Win32 + {690C304C-A70B-4B0F-BF61-8C51290BF444}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/DroneClientCpp/DroneClientCpp.vcxproj b/DroneClientCpp/DroneClientCpp.vcxproj new file mode 100644 index 0000000..4588522 --- /dev/null +++ b/DroneClientCpp/DroneClientCpp.vcxproj @@ -0,0 +1,141 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 17.0 + {690C304C-A70B-4B0F-BF61-8C51290BF444} + v4.7.2 + ManagedCProj + DroneClientCpp + 10.0 + + + + Application + true + v143 + true + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + true + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + Level3 + _DEBUG;%(PreprocessorDefinitions) + + + + + + + + Level3 + WIN32;_DEBUG;%(PreprocessorDefinitions) + + + + + + + + Level3 + WIN32;NDEBUG;%(PreprocessorDefinitions) + + + + + + + + Level3 + NDEBUG;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + CppForm + + + + + + FormMain.h + + + + + + \ No newline at end of file diff --git a/DroneClientCpp/DroneClientCpp.vcxproj.filters b/DroneClientCpp/DroneClientCpp.vcxproj.filters new file mode 100644 index 0000000..6c37b72 --- /dev/null +++ b/DroneClientCpp/DroneClientCpp.vcxproj.filters @@ -0,0 +1,42 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Исходные файлы + + + Исходные файлы + + + Исходные файлы + + + + + Файлы заголовков + + + Файлы заголовков + + + Файлы заголовков + + + Файлы заголовков + + + \ No newline at end of file diff --git a/DroneClientCpp/DroneClientCpp.vcxproj.user b/DroneClientCpp/DroneClientCpp.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/DroneClientCpp/DroneClientCpp.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/DroneClientCpp/DroneData.h b/DroneClientCpp/DroneData.h new file mode 100644 index 0000000..63a3a3d --- /dev/null +++ b/DroneClientCpp/DroneData.h @@ -0,0 +1,77 @@ +#pragma once + +#include +#include + +using namespace System; +using namespace System::Runtime::InteropServices; + +namespace DroneData { + + public enum class DataMode : unsigned short + { + None = 0, Response = 1, Request = 2 + }; + + public enum class DataType : unsigned short + { + None = 0, Head = 1, + DataIMU = 1001, DataPos = 1002, + DataMotor4 = 2001, DataMotor6 = 2002 + }; + + public value struct DataHead + { + public: + int Size; + DataMode Mode; + DataType Type; + + static const int StrLen = sizeof(DataHead); + }; + + public value struct XYZ + { + public: + float X, Y, Z; + }; + + public value struct DataIMU + { + public: + DataHead Head; + XYZ Acc, Gyr, Mag; + + static const int StrLen = sizeof(DataIMU); + }; + + public value struct DataPos + { + public: + DataHead Head; + XYZ Local; + float LiDAR; + + static const int StrLen = sizeof(DataPos); + }; + + public value struct DataMotor4 + { + public: + DataHead Head; + unsigned long long Count; + float UL, UR, DL, DR; + + static const int StrLen = sizeof(DataMotor4); + }; + + public value struct DataMotor6 + { + public: + DataHead Head; + unsigned long long Count; + float UL, UR, LL, RR, DL, DR; + + static const int StrLen = sizeof(DataMotor6); + }; +} \ No newline at end of file diff --git a/DroneClientCpp/FormMain.cpp b/DroneClientCpp/FormMain.cpp new file mode 100644 index 0000000..dfbdfbc --- /dev/null +++ b/DroneClientCpp/FormMain.cpp @@ -0,0 +1,12 @@ +#include "FormMain.h" + +#include + +using namespace DroneClientCpp; + +int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { + Application::EnableVisualStyles(); + Application::SetCompatibleTextRenderingDefault(false); + Application::Run(gcnew FormMain); + return 0; +} \ No newline at end of file diff --git a/DroneClientCpp/FormMain.h b/DroneClientCpp/FormMain.h new file mode 100644 index 0000000000000000000000000000000000000000..3af627c98c4ce3956cfdbfd7256a7590fb8cd03f GIT binary patch literal 75238 zcmeHQS#umma_)zDu_OHE2fyrkmWtRIhF1~*0U`(<5-^_6GmQ*;#g) z?PUkqzhwVx9-m~#=EzC*Q?`%e$I;)7ZjV+*|24Wk z8V6UAemU*CkmnMQJdZNk?o~xR9zycV>`r!qu^nI>ms1`(=2LKegHJA?n_Z&~S9Ml#`*I{eW@;f!qwE=5k8I4dy;*?8JFPlCc9y-Zgb^Ewt;b+fyUdZML3!VcuiZK zB%pi(DhJTPB}PM=Uv#AT7o(MZ(0T`2l>b}2KF0{UQdY}%(JTmU*>;Bjap+baS+ZBYbr&8ZCAG!%AT_qSv;ULTND?87E4y z%FnGdPoUE`K#>#Z_tMy0wChrPi_c$~xZDGWb9mk%p7+c(7x0krM{jumDzwoU9yEsc zyVtp~MGq_UIoAVSNq+W5>C)fuK2bfW7pq*8?C%)kG2-xQ^n9PbQqkx87}>Fjxm}}; ze?SxYIG=#F@1c6VJ`pU7()7>{V+;uQLPuE&r=#4QWa8CF) zc=`J1TRfIVH}L-&p84((y#DrRdGw!%gAGK;k{1Q8ZFF?M7|pt$a4tK;hy}3@p#8YD z{yXPKl+mT6Jj(5KZ2WTqZH5?p0ea&p3eyIhIb&y)+fV7o?Dz*`$x{(plZi+wmjMx4I8*agm z-e*6+SB`>XJJ}PA>l`EG|G3VY^4*5EUV+|;;YeJTcRSg4kmDShOv7gjK6;5i<_{d( zE9d==!L?I^M$9tOaC`_3%;3&}qI=mhX!b6+znk)>|HVJ`wVYZHPa)BJjL}+|zG{zz z+&6(A`^l_b&&xKUuf0T8DE6(d=Z;@!*_#2ro$EVbwfe&WzKGnQ?kPGfpq( zV6hjCdFFF6yY^ycxdlw!%U*v(^Haq0UktXsHs~a1SbolOBAwTZ|9e=M_CLP}mz}Kt z7*S6B$B1(3KSq?(EMr7@Hjk02)mJf+D$n%jT`v}x1%*`!%|O%US{Fc`?L={2tWO!w zPS$@cD5w5oK{;(V#_slhsXS*H3(9j|vB2z!RghE}dik2*arQV-G?eq%P8N0Ld>+hb zJP&3xp1W92rOBhq_4W*Fw={g7BCC-+i#gf3S%

;vSRr-aC_-rQuqR#qW}hjg?id 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 310, 17 + + \ No newline at end of file diff --git a/DroneClientCpp/MyForm.cpp b/DroneClientCpp/MyForm.cpp new file mode 100644 index 0000000..7c411c2 --- /dev/null +++ b/DroneClientCpp/MyForm.cpp @@ -0,0 +1,12 @@ +#include "MyForm.h" + +#include + +using namespace DroneClientCpp; + +int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { + Application::EnableVisualStyles(); + Application::SetCompatibleTextRenderingDefault(false); + Application::Run(gcnew MyForm); + return 0; +} \ No newline at end of file diff --git a/DroneClientCpp/MyForm.h b/DroneClientCpp/MyForm.h new file mode 100644 index 0000000000000000000000000000000000000000..bdc5a398f06f438110605991bd029818f65593c3 GIT binary patch literal 4284 zcmb_fO>fgc5S_zbg2at8GDSi`e6$HE4QbOhX{kV@4Wb2ZpfqtqApKC{P(DCTwvf;TOAMhp1&myEPZj@p~jU{$;AZ=t>TYFkTluL+lS+!JCEhEM? z9d~oDs|IE_)fRAQVtx}Vle+BaLhoTl%=uH;Y548KpV(iEZyx?JLvCYla-gK`sbc>Y ztSe)dR#tJ}z?)UfuE4%!wWeO_H=FoxU}h8luhiqn_ju<#rWE8?3XkbH3^ap^;840Y zj2+|(VXb1+d6}Bw>$s4ASy>k~6Hm(7Cq{JuhA=aIjorMwY=YGRF4mh5VELglE=8Ql zLodeGwZh^bM|XN&ySSE+%PU|K`9}QecxHBQU`+JZ@T*6&$`Es^B6DPm%FeyvvKeC$~IL>R8KMTnRC2t7jTjFJomx z>o%IJSiP<#ceM>qFmf$o#c$w8d${r?II@Q^xlsXE;#y>@)zX}KZtJXf<(g_GrdNbO zJ^{b6Ji<+0&C2*!vximgFJiO1PJ2 z_?+E;4|}t#G_h~VLJE_GsMfK*&h}*=7V(@lx-R#@t}ljm(}OBJ$j2;e{{iej)XZeQ ze+&0sn#1Y?Ef@Tk2)qTOe0it&J%MFIAQ^yH>|dK0cjb%jLWV$(wToB>c$(n7d!o&b zv+4Dz%aaFM$E=Kbj&sm_7rcN4I-ms>mVvxJBn`l39A&&GG=)vV0o8BcrIjSj==+yGa44o|WbJ3pG) zy5ce-zp7-j@oI8!z!TF=`Keldq}jy0wANZanr<=OiJ0@i?MKY|%X`Xqx+b&#$j_Z( zrna}S`ZKKK_boe3TFNYCj*_+MIvVG511tJiPbqq5v+!rsQMmk0+C(g~v3`$O@hdOR Rb$*e=XxaYyBIK + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/DroneClientCpp/NetClient.cpp b/DroneClientCpp/NetClient.cpp new file mode 100644 index 0000000..e3e7c78 --- /dev/null +++ b/DroneClientCpp/NetClient.cpp @@ -0,0 +1,105 @@ +#include "NetClient.h" + +namespace DroneSimulator { + + // Конструктор ConnectData + NetClient::ConnectData::ConnectData(bool connect, Socket^ server) + { + Connect = connect; + Server = server; + } + + // Конструктор ReceiveData + NetClient::ReceiveData::ReceiveData(array^ buffer, int size, Socket^ server) + { + Buffer = buffer; + Size = size; + Server = server; + } + + // Конструктор NetClient + NetClient::NetClient() + { + Connected = false; + ServerSocket = nullptr; + DataServer = gcnew ServerData(); // Инициализация DataServer + } + + // Реализация метода Connect + NetClient::ClientState NetClient::Connect(String^ Addr, int Port, ClientCallback^ Connection, ClientCallback^ Receive) + { + if (Connected) + { + Close(); + return ClientState::Stop; + } + + ConnectionCallback = Connection; + ReceiveCallback = Receive; + + IPEndPoint^ ep = gcnew IPEndPoint(IPAddress::Parse(Addr), Port); + ServerSocket = gcnew Socket(AddressFamily::InterNetwork, SocketType::Stream, ProtocolType::Tcp); + + try { ServerSocket->Connect(ep); } + catch (...) { ServerSocket->Close(); return ClientState::Error; } + + Connected = true; + + ConnectionCallback(gcnew ConnectData(true, ServerSocket)); + + ReceiveData^ receiveData = gcnew ReceiveData(DataServer->buffer, ServerData::size, ServerSocket); + + try { ServerSocket->BeginReceive(DataServer->buffer, 0, ServerData::size, SocketFlags::None, gcnew AsyncCallback(this, &NetClient::ReadCallback), receiveData); } + catch (...) {} + + return ClientState::Connected; + } + + // Реализация метода Close + void NetClient::Close() + { + try { ServerSocket->Shutdown(SocketShutdown::Both); } + catch (...) {} + ServerSocket->Close(); + Connected = false; + } + + // Реализация метода Send + void NetClient::Send(array^ data) + { + if (ServerSocket != nullptr && Connected) + { + try { ServerSocket->Send(data); } + catch (...) {} + } + } + + // Реализация метода ReadCallback + void NetClient::ReadCallback(IAsyncResult^ ar) + { + ReceiveData^ cd = (ReceiveData^)ar->AsyncState; + if (cd == nullptr) return; + + int bytes = 0; + try { bytes = ServerSocket->EndReceive(ar); } + catch (...) {} + + if (bytes == 0) + { + ServerSocket->Close(); + Connected = false; + + if (ServerSocket != nullptr) + { + ConnectionCallback(gcnew ConnectData(false, nullptr)); + } + + return; + } + + ReceiveCallback(gcnew ReceiveData(cd->Buffer, bytes, ServerSocket)); + + try { ServerSocket->BeginReceive(cd->Buffer, 0, ServerData::size, SocketFlags::None, gcnew AsyncCallback(this, &NetClient::ReadCallback), cd); } + catch (...) {} + } +} \ No newline at end of file diff --git a/DroneClientCpp/NetClient.h b/DroneClientCpp/NetClient.h new file mode 100644 index 0000000..adfe19e --- /dev/null +++ b/DroneClientCpp/NetClient.h @@ -0,0 +1,68 @@ +#pragma once + +#include +#include + +#using +#using + +using namespace System; +using namespace System::Net; +using namespace System::Net::Sockets; + +namespace DroneSimulator { + + public ref class NetClient + { + public: + ref class ConnectData + { + public: + bool Connect; + Socket^ Server; + + ConnectData(bool connect, Socket^ server); + }; + + ref class ReceiveData + { + public: + array^ Buffer; + int Size; + Socket^ Server; + + ReceiveData(array^ buffer, int size, Socket^ server); + }; + + private: + ref class ServerData + { + public: + literal int size = 1024; + array^ buffer = gcnew array(size); + }; + + bool Connected; + Socket^ ServerSocket; + ServerData^ DataServer; + + public: + delegate void ClientCallback(Object^ o); + + private: + ClientCallback^ ConnectionCallback; + ClientCallback^ ReceiveCallback; + + public: + NetClient(); // Добавлен конструктор + + enum class ClientState { Error, Connected, Stop }; + + ClientState Connect(String^ Addr, int Port, ClientCallback^ Connection, ClientCallback^ Receive); + void Close(); + void Send(array^ data); + + private: + void ReadCallback(IAsyncResult^ ar); + }; +} \ No newline at end of file diff --git a/DroneClientCpp/Source.cpp b/DroneClientCpp/Source.cpp new file mode 100644 index 0000000..6c8d9fb --- /dev/null +++ b/DroneClientCpp/Source.cpp @@ -0,0 +1,11 @@ +#include "MyForm.h" + +using namespace MyWinFormsApp; // ???????????? ???? ?????? ??????? + +[STAThread] +int main(array^ args) { + Application::EnableVisualStyles(); // ???????? ??????????? ????? ????????? ?????????? + Application::SetCompatibleTextRenderingDefault(false); // ????????? ?????????? ?????? + Application::Run(gcnew MyForm()); // ?????? ????? + return 0; +} \ No newline at end of file