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.vcxproj b/DroneClientCpp/DroneClientCpp.vcxproj index ce872f9..9afbb8d 100644 --- a/DroneClientCpp/DroneClientCpp.vcxproj +++ b/DroneClientCpp/DroneClientCpp.vcxproj @@ -118,14 +118,14 @@ - - + CppForm + diff --git a/DroneClientCpp/DroneClientCpp.vcxproj.filters b/DroneClientCpp/DroneClientCpp.vcxproj.filters index 7b8fd21..c9e3b4e 100644 --- a/DroneClientCpp/DroneClientCpp.vcxproj.filters +++ b/DroneClientCpp/DroneClientCpp.vcxproj.filters @@ -18,15 +18,15 @@ Исходные файлы - - Исходные файлы - Файлы заголовков - + + Файлы заголовков + + Файлы заголовков diff --git a/DroneClientCpp/FormMain.h b/DroneClientCpp/FormMain.h index ec63414..1c0565b 100644 Binary files a/DroneClientCpp/FormMain.h and b/DroneClientCpp/FormMain.h differ diff --git a/DroneClientCpp/NetClient.h b/DroneClientCpp/NetClient.h new file mode 100644 index 0000000..dd578dd --- /dev/null +++ b/DroneClientCpp/NetClient.h @@ -0,0 +1,166 @@ +// NetClient.h +#pragma once + +#include +#include + +#using +#using + +using namespace System; +using namespace System::Net; +using namespace System::Net::Sockets; +using namespace System::Runtime::InteropServices; + +namespace DroneSimulator +{ + public ref class NetClient + { + public: + // Вложенный класс для данных подключения + ref class ConnectData + { + public: + property bool Connect; + property Socket^ Server; + }; + + // Вложенный класс для данных приема + ref class ReceiveData + { + public: + property array^ Buffer; + property int Size; + property Socket^ Server; + }; + + // Состояния клиента + enum class ClientState { Error, Connected, Stop }; + + // Делегат для callback-функций + delegate void ClientCallback(Object^ o); + + NetClient() + { + Connected = false; + ServerSocket = nullptr; + DataServer = gcnew ServerData(); + } + + ~NetClient() + { + Close(); + } + + ClientState Connect(String^ addr, int port, ClientCallback^ connectionCallback, ClientCallback^ receiveCallback) + { + if (Connected) + { + Disconnect(); + return ClientState::Stop; + } + + ConnectionCallback = connectionCallback; + ReceiveCallback = receiveCallback; + + try + { + IPEndPoint^ ep = gcnew IPEndPoint(IPAddress::Parse(addr), port); + ServerSocket = gcnew Socket(AddressFamily::InterNetwork, SocketType::Stream, ProtocolType::Tcp); + ServerSocket->Connect(ep); + + Connected = true; + + // Уведомление о подключении + ConnectData^ connectData = gcnew ConnectData(); + connectData->Connect = true; + connectData->Server = ServerSocket; + ConnectionCallback(connectData); + + // Начало приема данных + ReceiveData^ receiveData = gcnew ReceiveData(); + receiveData->Buffer = DataServer->buffer; + receiveData->Size = ServerData::size; + receiveData->Server = ServerSocket; + + ServerSocket->BeginReceive(DataServer->buffer, 0, ServerData::size, + SocketFlags::None, gcnew AsyncCallback(this, &NetClient::ReadCallback), receiveData); + + return ClientState::Connected; + } + catch (Exception^) + { + if (ServerSocket != nullptr) + ServerSocket->Close(); + return ClientState::Error; + } + } + + void Close() + { + Disconnect(); + } + + private: + ref class ServerData + { + public: + static const int size = 1024; + array^ buffer = gcnew array(size); + }; + + bool Connected; + Socket^ ServerSocket; + ServerData^ DataServer; + ClientCallback^ ConnectionCallback; + ClientCallback^ ReceiveCallback; + + void Disconnect() + { + if (ServerSocket != nullptr) + { + try { ServerSocket->Shutdown(SocketShutdown::Both); } + catch (...) {} + ServerSocket->Close(); + ServerSocket = nullptr; + } + Connected = false; + } + + void ReadCallback(IAsyncResult^ ar) + { + ReceiveData^ cd = safe_cast(ar->AsyncState); + if (cd == nullptr) return; + + int bytes = 0; + try { bytes = ServerSocket->EndReceive(ar); } + catch (...) {} + + if (bytes == 0) + { + Disconnect(); + + if (ConnectionCallback != nullptr) + { + ConnectData^ disconnectData = gcnew ConnectData(); + disconnectData->Connect = false; + disconnectData->Server = nullptr; + ConnectionCallback(disconnectData); + } + return; + } + + if (ReceiveCallback != nullptr) + { + ReceiveCallback(cd); + } + + try + { + ServerSocket->BeginReceive(cd->Buffer, 0, ServerData::size, + SocketFlags::None, gcnew AsyncCallback(this, &NetClient::ReadCallback), cd); + } + catch (...) {} + } + }; +} \ No newline at end of file