первый

This commit is contained in:
2024-11-01 12:23:13 +05:00
parent 801d9d33fa
commit 0688c46a7e
226 changed files with 162921 additions and 0 deletions

277
devices/SocketPort.cpp Normal file
View File

@ -0,0 +1,277 @@
//---------------------------------------------------------------------------
#include "SocketPort.h"
//---------------------------------------------------------------------------
#if defined(_WIN32) || defined(_WINDOWS)
#include <windows.h>
//#include <minwinbase.h>
#include <winnt.h>
//#include <fileapi.h>
#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "Mswsock.lib")
#pragma comment(lib, "AdvApi32.lib")
#else
#endif
//---------------------------------------------------------------------------
SocketPort::SocketPort()
{
//id = 0;
bOpen = false;
my_sock=0;
}
//------------------------------------------------------------------------------
SocketPort::~SocketPort()
{
//Close();
}
//------------------------------------------------------------------------------
//#define PORT 666
//#define SERVERADDR "*.*.*.*" //Звёздочками пометил свой IP
//------------------------------------------------------------------------------
bool SocketPort::Open(const char* IPAddress,int PortNo)
{
if (bOpen)
Close();
#if defined(_WIN32) || defined(_WINDOWS)
WORD wVersionRequested;
WSADATA wsaData;
int err;
//Шаг 1 - инициализация
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if(err)
{
printf("WSAStart error %d\n", WSAGetLastError());
bOpen = false;
return bOpen;
}
// Шаг 2 - создание сокета
my_sock = socket(AF_INET, SOCK_STREAM, 0);
if (my_sock < 0)
{
printf("Socket() error %d\n", WSAGetLastError());
bOpen = false;
return bOpen;
}
//Отключаю буферизацию для маленьких пакетов, алгоритм Нейгла 200 миллисекунд
DWORD value = 1;
if (setsockopt(my_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&value, sizeof(value)) != 0){
printf("setsockopt() error %d\n", WSAGetLastError());
bOpen = false;
return bOpen;
}
//Задаю таймаут для чтения из сокета в миллисекундах те. *1000 (Ниже есть отдельная функция для этого)
DWORD timeout = 1 * 1000;
if(setsockopt(my_sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout))!=0)
{
printf("setsockopt() error %d\n", WSAGetLastError());
bOpen = false;
return bOpen;
}
// Шаг 3 - установка соединения
// заполнение структуры sockaddr_in - указание адреса и порта сервера
sockaddr_in dest_addr;
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(PortNo);
HOSTENT *hst;
// преобразование IP адреса из символьного в сетевой формат
if (inet_addr(IPAddress) != INADDR_NONE)
dest_addr.sin_addr.s_addr = inet_addr(IPAddress);
else
{
//Новая функция на замен gethostbyname
/* struct addrinfo hints = { 0 }, * addrs;
int err = getaddrinfo(IPAddress, PortNo, &hints, &addrs);
if (err == 0)
{
// hst->h_addr_list содержит не массив адресов,
// а массив указателей на адреса
((unsigned long*)&dest_addr.sin_addr)[0] = ((unsigned long**)hst->h_addr_list)[0][0];
freeaddrinfo(addrs);
} else {
printf("Invalid address %s\n", IPAddress);
closesocket(my_sock);
WSACleanup();
bOpen = false;
return bOpen;
}*/
// попытка получить IP адрес по доменному имени сервера
hst = gethostbyname(IPAddress);
if (hst!=NULL)
// hst->h_addr_list содержит не массив адресов,
// а массив указателей на адреса
((unsigned long *)&dest_addr.sin_addr)[0] = ((unsigned long **)hst->h_addr_list)[0][0];
else
{
printf("Invalid address %s\n", IPAddress);
closesocket(my_sock);
WSACleanup();
bOpen = false;
return bOpen;
}
}
// адрес сервера получен - пытаемся установить соединение
if (connect(my_sock, (sockaddr *)&dest_addr, sizeof(dest_addr)))
{
printf("Connect error %d\n", WSAGetLastError());
bOpen = false;
return bOpen;
}
//printf("Soedinenie s %s uspeshno ustanovlenno\n \ Type quit for quit\n\n", IPAddress);
bOpen = true;
#else
struct sockaddr_in server;
//Create socket
my_sock = socket(AF_INET , SOCK_STREAM , 0);
if (my_sock == -1)
{
printf("Could not create socket");
}
puts("Socket created");
server.sin_addr.s_addr = inet_addr(IPAddress);
server.sin_family = AF_INET;
server.sin_port = htons( PortNo );
//Connect to remote server
if (connect(my_sock , (struct sockaddr *)&server , sizeof(server)) < 0)
{
perror("connect failed. Error");
return 1;
}
puts("Connected\n");
#endif
return true;
}
//------------------------------------------------------------------------------
//Сколько ждать данных в миллисекундах при чтении данных
bool SocketPort::SetTimeout(unsigned long time)
{
#if defined(_WIN32) || defined(_WINDOWS)
DWORD timeout = time;
if(setsockopt(my_sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout))!=0)
{
return false;
}
#else
struct timeval tv;
tv.tv_sec = time/1000;
tv.tv_usec = (time%1000)*1000;
int result=setsockopt(my_sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
if(result!=0)
{
return false;
}
result=setsockopt(my_sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
if(result!=0)
{
return false;
}
#endif
return true;
}
//------------------------------------------------------------------------------
bool SocketPort::Close()
{
#if defined(_WIN32) || defined(_WINDOWS)
if (my_sock)
closesocket(my_sock);
//WSACleanup(); Закоментил так как сокеты могут использоваться во многих местах
#else
shutdown(my_sock,2);
close(my_sock);
#endif
bOpen = false;
return true;
}
//------------------------------------------------------------------------------
unsigned long SocketPort::Write(const void* lpBuffer,unsigned long nNumberOfBytesToWrite)
{
return send(my_sock,(const char*)lpBuffer,nNumberOfBytesToWrite,0);
}
//------------------------------------------------------------------------------
unsigned char SocketPort::WriteChar(signed char ch)
{
return (unsigned char)Write(&ch,1);
}
//------------------------------------------------------------------------------
unsigned char SocketPort::WriteUChar(unsigned char ch)
{
return (unsigned char)Write(&ch,1);
}
//------------------------------------------------------------------------------
unsigned char SocketPort::WriteUInt(unsigned int val)
{
return (unsigned char)Write(&val,4);
}
//------------------------------------------------------------------------------
//Для MQTT протокола
int SocketPort::writeUTF8(std::string str)
{
if(str.length()>=65535) return 0;
unsigned short size=str.length();
int len=0;
len+=WriteUChar(((uint8_t*)&size)[1]);
len+=WriteUChar(((uint8_t*)&size)[0]);
len+=Write(str.c_str(),str.length());
return len;
}
//------------------------------------------------------------------------------
//Читать столько сколько за раз придёт
int SocketPort::Read(void* lpBuffer,unsigned long nNumberOfBytesToRead)
{
if(nNumberOfBytesToRead<=0) return 0;
return recv(my_sock,(char*)lpBuffer,nNumberOfBytesToRead,0);
}
//------------------------------------------------------------------------------
//Попытаться и заполнить весь буфер
//Результат количество прочитанных байт
int SocketPort::ReadAll(void* lpBuffer,unsigned long nNumberOfBytesToRead)
{
if(nNumberOfBytesToRead==0) return 0;
int len;
int pos=0;
while(true){
len=recv(my_sock,&((char*)lpBuffer)[pos],nNumberOfBytesToRead,0);
if(len==-1) break;
if(len==0) break;
pos+=len;
nNumberOfBytesToRead-=len;
if(nNumberOfBytesToRead==0)
break;
}
return pos;
}
//------------------------------------------------------------------------------
//Прочитать и изменить порядок байт
int SocketPort::ReadR(void* lpBuffer,unsigned long nNumberOfBytesToRead)
{
if(nNumberOfBytesToRead==0) return 0;
int result=recv(my_sock,(char*)lpBuffer,nNumberOfBytesToRead,0);
if(result>1){
char ch;
int d=result/2;
for(int i=0;i<d;i++){
ch=((char*)lpBuffer)[i];
((char*)lpBuffer)[i]=((char*)lpBuffer)[result-i-1];
((char*)lpBuffer)[result-i-1]=ch;
}
}
return result;
}
//------------------------------------------------------------------------------