первый
This commit is contained in:
277
devices/SocketPort.cpp
Normal file
277
devices/SocketPort.cpp
Normal 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;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user