mirror of
https://github.com/HEYAHONG/HCppBox.git
synced 2025-05-10 00:49:25 +08:00
180 lines
4.6 KiB
C++
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__
|