Как получить пакет UDP через необработанные сокеты на С++ в Windows?C++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Как получить пакет UDP через необработанные сокеты на С++ в Windows?

Сообщение Anonymous »

Я пытался получить UDP-пакет со следующей функцией:

Код: Выделить всё

int UDP::recv(byte* data, const uint16_t dataLen, uint16_t srcPort, IPV4& srcIp)
{
const size_t totalHeadersLen = IP_HEADERS_SIZE + UDP_HEADERS_SIZE;

byte* recvBuffer = new byte[UINT16_MAX];
sockaddr_in srcAddr;
int srcAddrSize = sizeof(srcAddr);

while (true) // Keep receiving until reaching a valid packet
{
// Receive the packet
int packetSize = recvfrom(
_socket,
reinterpret_cast(recvBuffer),
UINT16_MAX,
0,
reinterpret_cast(&srcAddr),
&srcAddrSize);

// Check for errors
if (packetSize == SOCKET_ERROR || packetSize < totalHeadersLen)
{
delete[] recvBuffer;
throw std::runtime_error(std::to_string(WSAGetLastError()));
}

// Parse IP header (20 bytes for IPv4)
const byte* ipHeader = recvBuffer;

// Extract source IP
srcIp[0] = ipHeader[12];
srcIp[1] = ipHeader[13];
srcIp[2] = ipHeader[14];
srcIp[3] = ipHeader[15];

const byte* udpHeader = recvBuffer + IP_HEADERS_SIZE;

UDPHeaders headers;
headers.srcPort = ntohs(*reinterpret_cast(udpHeader));
headers.dstPort = ntohs(*reinterpret_cast(udpHeader + 2));
headers.length = ntohs(*reinterpret_cast(udpHeader + 4));
headers.checksum = ntohs(*reinterpret_cast(udpHeader + 6));

// Check if the destination port matches the local port
if (headers.dstPort != _localPort)
{
// Ignore this packet
continue;
}

// Set the source port
srcPort = headers.srcPort;

// Calculate the checksum and verify it matches
size_t receivedDataLen = headers.length - UDP_HEADERS_SIZE;
uint16_t checksum = calcChecksum(headers, srcIp, _localAddr, recvBuffer + totalHeadersLen, receivedDataLen);
if (checksum != headers.checksum)
{
// Ignore this packet
continue;
}

// Verify data length and buffer size
if (dataLen < receivedDataLen)
{
delete[] recvBuffer;
throw std::runtime_error("Data buffer is too small.");
}

// Copy the UDP payload to the provided buffer
std::memcpy(data, recvBuffer + totalHeadersLen, receivedDataLen);

break;
}

delete[] recvBuffer;
return 0;
}
Он блокирует функцию Recvfrom.
Создание сокета осуществляется в другом построителе класса UDP.
Вот часть создания:

Код: Выделить всё

_socket = socket(AF_INET, SOCK_RAW, POROTO_ID);
if (_socket == INVALID_SOCKET)
{
WSACleanup();
throw std::runtime_error(std::to_string(WSAGetLastError()));
}

struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = 0;
addr.sin_addr.s_addr = INADDR_ANY;

if (bind(_socket, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
{
closesocket(_socket);
WSACleanup();
throw std::runtime_error(std::to_string(WSAGetLastError()));
}
Пакет, который я пытался получить, был успешно отправлен (я дважды проверил с помощью Wireshark).
Единственный способ решения этой проблемы, который я нашел, — это путем реализации сетевого уровня (IPV4), чего я предпочитаю не делать.

Подробнее здесь: https://stackoverflow.com/questions/792 ... in-windows
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»