HCppBox/test/ModbusTCPClient/ModbusSocketIo.h
2024-10-25 16:46:45 +08:00

180 lines
4.6 KiB
C++

#ifndef __MODBUSSOCKETIO_H_INCLUDED__
#define __MODBUSSOCKETIO_H_INCLUDED__
#include "HCPPBox.h"
#include "hbox.h"
class ModbusSocketIo
{
private:
int socket_fd;
public:
bool IsConnected()
{
return socket_fd!=INVALID_SOCKET;
}
size_t send(const uint8_t *buffer,size_t length)
{
size_t offset=0;
while( IsConnected() && offset < length)
{
int sendlen=::send(socket_fd,(const char *)(buffer+offset),length-offset,0);
if(sendlen>0)
{
offset+=sendlen;
}
if(sendlen==0)
{
//连接已断开
closesocket(socket_fd);
socket_fd=INVALID_SOCKET;
}
}
return offset;
}
size_t recv(uint8_t *buffer,size_t length)
{
if(!IsConnected())
{
return 0;
}
int recvlen=::recv(socket_fd,(char *)buffer,length,0);
if(recvlen==0)
{
//连接已断开
closesocket(socket_fd);
socket_fd=INVALID_SOCKET;
}
if(recvlen<0)
{
int socket_errno=errno;
#ifdef WIN32
if(socket_errno!=EWOULDBLOCK)
#else
if(socket_errno!=EAGAIN)
#endif // WIN32
{
closesocket(socket_fd);
socket_fd=INVALID_SOCKET;
}
}
if(recvlen > 0)
{
return recvlen;
}
return 0;
}
bool connect_ipv4(const char *host,const char *port)
{
if(IsConnected())
{
return false;
}
bool ret=false;
socket_fd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(socket_fd!=INVALID_SOCKET)
{
HCPPSocketAddressIPV4 addr= {0};
{
//DNS查询
struct addrinfo hints = { 0 };
struct addrinfo *ai_result = NULL;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_CANONNAME;
hints.ai_protocol = IPPROTO_TCP;
if (getaddrinfo(host, port, &hints, &ai_result) == 0)
{
for (struct addrinfo* info = ai_result; info != NULL; info = info->ai_next)
{
if (info->ai_family == AF_INET)
{
addr = *(HCPPSocketAddressIPV4*)info->ai_addr;
ret=true;
}
}
freeaddrinfo(ai_result);
}
}
if(ret)
{
//连接
if(0!=connect(socket_fd,(HCPPSocketAddress *)&addr,sizeof(addr)))
{
ret=false;
}
else
{
{
//设定接收超时5ms
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 500*1000;
ret=(0==setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof(tv)));
}
}
}
}
if(!ret)
{
if(socket_fd!=INVALID_SOCKET)
{
closesocket(socket_fd);
socket_fd=INVALID_SOCKET;
}
}
return ret;
}
bool disconnect()
{
if(IsConnected())
{
closesocket(socket_fd);
socket_fd=INVALID_SOCKET;
return true;
}
return false;
}
private:
static size_t _send(modbus_io_interface_t *io,const uint8_t *adu,size_t adu_length)
{
if(io==NULL || io->usr == NULL)
{
return 0;
}
ModbusSocketIo &IO=*(ModbusSocketIo *)io->usr;
return IO.send(adu,adu_length);
}
static size_t _recv(modbus_io_interface_t *io,uint8_t *buffer,size_t buffer_length)
{
if(io==NULL || io->usr == NULL)
{
return 0;
}
ModbusSocketIo &IO=*(ModbusSocketIo *)io->usr;
return IO.recv(buffer,buffer_length);
}
public:
ModbusSocketIo():socket_fd{INVALID_SOCKET}
{
}
virtual ~ModbusSocketIo()
{
disconnect();
}
modbus_io_interface_t GetIoInterface()
{
modbus_io_interface_t ret = modbus_io_interface_default();
ret.usr=(ModbusSocketIo *)this;
ret.send=_send;
ret.recv=_recv;
return ret;
}
};
#endif // __MODBUSSOCKETIO_H_INCLUDED__