Я написал 2 простых класса udp(путём нарезания какого-то кода сервера и клиента).
#include "usefull.h"
#include <winsock2.h>
#include <Ws2tcpip.h>
#pragma comment (lib, "Ws2_32.lib")
class IADDR
{
public:
sockaddr_in addr;
IADDR()
{
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
}
IADDR(string ip,int16_t port)
{
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
char buff1[100];
InetPton(AF_INET, ip.c_str(), &addr.sin_addr.s_addr);
addr.sin_port = htons(port);
//addr.sin_addr.s_addr = htonl(addr.sin_addr.s_addr);
}
};
class UDP
{
public:
UDP()
{
ok = 0;
if (!is_st)
{
WSADATA w;
int res = WSAStartup(MAKEWORD(2, 2), &w);
if (res != 0)
{
return;
}
is_st = 1;
}
}
~UDP()
{
if (ok == 1)
{
closesocket(sock);
ok = 0;
}
}
void set(IADDR a)
{
if (ok == 1)
{
closesocket(sock);
ok = 0;
}
if (is_st == 0)
return;
addr = a;
sock = socket(AF_INET, SOCK_DGRAM, 0);
u_long nMode = 1;
if (ioctlsocket(sock, FIONBIO, &nMode) == SOCKET_ERROR)
{
closesocket(sock);
}
ok = 1;
}
void send(vector<byte> v)
{
send(&v[0], v.size());
}
void send(const byte* buff, uint32_t size)
{
if (ok == 0)
return;
int len = sizeof(addr.addr);
sendto(sock, (char*)buff, size, 0, (sockaddr*)&addr.addr, len);
}
bool recv(vector<byte> &data)
{
if (ok == 0)
return 0;
data.resize(1024);
sockaddr_in serverInfo;
int fromlen = sizeof(addr.addr);
uint len = recvfrom(sock, (char*)&data[0], 1024, 0, (sockaddr*)&serverInfo, &fromlen);
if (len != SOCKET_ERROR)
{
data.resize(len);
return 1;
}
else
{
data.resize(0);
return 0;
}
}
private:
int sock;
IADDR addr;
int ok;
static int is_st;
friend class UDPSERVER;
};
class UDPSERVER
{
public:
UDPSERVER()
{
ok = 0;
if (!UDP::is_st)
{
WSADATA w;
int res = WSAStartup(MAKEWORD(2, 2), &w);
if (res != 0)
{
return;
}
UDP::is_st = 1;
}
}
~UDPSERVER()
{
if (ok == 1)
{
closesocket(sock);
ok = 0;
}
}
void set(USHORT port)
{
if (UDP::is_st == 0)
return;
if (ok == 1)
{
closesocket(sock);
ok = 0;
}
struct sockaddr_in sv_ip;
sv_ip.sin_family = AF_INET;
sv_ip.sin_port = htons(port);
sv_ip.sin_addr.s_addr = INADDR_ANY;
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == INVALID_SOCKET)
{
return;
}
u_long nMode = 1;
if (ioctlsocket(sock, FIONBIO, &nMode) == SOCKET_ERROR)
{
closesocket(sock);
return;
}
if (bind(sock, (sockaddr*)&sv_ip, sizeof(sv_ip)) == SOCKET_ERROR)
{
closesocket(sock);
return;
}
ok = 1;
}
void send(vector<byte> v, IADDR &a)
{
send(&v[0], v.size(), a);
}
void send(const byte* buff, uint32_t size, IADDR &a)
{
if (ok == 0)
return;
int fromlen = sizeof(a.addr);
sendto(sock, (char*)buff, size, 0, (sockaddr*)&a.addr, fromlen);
}
bool recv(vector<byte> &data, IADDR &a)
{
if (ok == 0)
return 0;
data.resize(1024);
int fromlen = sizeof(a.addr);
int len = recvfrom(sock, (char*)&data[0], 1024, 0, (sockaddr*)&a.addr, &fromlen);
if (len != SOCKET_ERROR)
{
data.resize(len);
return 1;
}
else
{
data.resize(0);
return 0;
}
}
private:
SOCKET sock;
IADDR addr;
int ok;
};
int UDP::is_st = 0;
В сокетах я ничего не понимаю. Работает вроде правильно но не крашнется ли? И надо бы как-то его на линукс перевести но как? Использование boost не приемлимо!(ибо он 2 часа устанавливается да ещё и не с 1 раза). QT тоже не использовать т.к. у него есть лицензия.
Win компилю VS а линукс QTCreator.
Компилить под линукс даже не пытался т.к. явно под виндовс.
Для перевода кода на Linux вам потребуется изменить системные вызовы работы с сокетами на POSIX.
Если смотреть по порядку, первый ваш вызов - это преобразование строки, определяющей IPv4 адрес, в структуру адреса через InetPton. Ее необходимо заменить на следующее:
inet_pton(AF_INET, ip.c_str(), &addr.sin_addr);
Функция возвращает 1 в случае успеха.
Вызов WSAStartup и все, что с ним связано, на Linux вам не потребуется.
Функцию closesocket необходимо заменить на close. Параметр - дескриптор сокета sock.
Вызов socket для создания сокета не изменится, они идентичны в обоих системах. В случае успеха функция вернет неотрицательный дескриптор типа int.
Вызов ioctlsocket необходимо изменить на следующее:
int flags = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, flags | O_NONBLOCK);
fcntl в случае неудачи возвращает -1. В качестве альтернативы есть и FIONBIO вариант, но O_NONBLOCK входит в стандарт POSIX и использовать FIONBIO я не советую:
int opt = 1;
ioctl(sock, FIONBIO, &opt);
Вызов sendto идентичен на обоих системах, как и recvfrom. Обе функции возвращают -1 в случае неудачи.
Во всех вызовах соответственно надо переделать проверки на возвращаемые функциями значения. Также в Linux дескриптор сокета имеет тип int.
Примечание
На вашем месте я бы еще раз подумал об организации структуры вашего кода. Оба ваших класса во многом дублируют друг друга, а в некоторых местах есть неиспользуемые переменные.
Также, как заметил test123, вы используете сокет в неблокирующем режиме, соответственно попытки получить данные из сокета когда их там еще нет приведут к ошибке функции recvfrom. Если вам действительно нужен неблокирующий режим сокета, вы можете использовать select или pselect для ожидания входных данных.
Если вы используете Qt, то у него также есть свой вариант работы с сокетами через класс QUdpSocket. Его описание есть в официальной документации.
Как развивать веб-проекты в 2026 году: технологии, контент E-E-A-T и факторы доверия
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники