2025-04-04 00:05:34 +03:00

166 lines
4.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// NetClient.h
#pragma once
#include <Windows.h>
#include <vcclr.h>
#using <System.dll>
#using <System.Net.dll>
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<Byte>^ 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<Byte>^ buffer = gcnew array<Byte>(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<ReceiveData^>(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 (...) {}
}
};
}