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 0000000..3af627c Binary files /dev/null and b/DroneClientCpp/FormMain.h differ diff --git a/DroneClientCpp/FormMain.resx b/DroneClientCpp/FormMain.resx new file mode 100644 index 0000000..27962ab --- /dev/null +++ b/DroneClientCpp/FormMain.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 0000000..bdc5a39 Binary files /dev/null and b/DroneClientCpp/MyForm.h differ diff --git a/DroneClientCpp/MyForm.resx b/DroneClientCpp/MyForm.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/DroneClientCpp/MyForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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