2023-11-21 20:28:23 +08:00
|
|
|
|
#include "if_tcp.h"
|
2023-11-26 23:05:35 +08:00
|
|
|
|
#include "QNetworkConfigurationManager"
|
|
|
|
|
#include "QThread"
|
2023-11-21 20:28:23 +08:00
|
|
|
|
|
2023-12-29 09:41:37 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const int keepalive = 1; // 开启keepalive属性
|
|
|
|
|
const int keepidle = 5; // 如果连接在5秒内没有任何数据来往则进行探测
|
|
|
|
|
const int keepinterval = 3; // 探测时发包的时间间隔为3秒
|
|
|
|
|
const int keepcount = 3; // 尝试探测的次数, 如果第一次探测包就收到响应,则不在继续探测
|
|
|
|
|
|
|
|
|
|
#if 1
|
|
|
|
|
#include <sys/socket.h>
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <netinet/tcp.h>
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
|
|
|
|
|
|
// 开启TCP心跳检测机制
|
|
|
|
|
int enableKeepalive(int fd) {
|
|
|
|
|
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive)) < 0) return -1;
|
|
|
|
|
if (setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &keepidle, sizeof(keepidle)) < 0) return -1;
|
|
|
|
|
if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &keepinterval, sizeof(keepinterval)) < 0) return -1;
|
|
|
|
|
if (setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &keepcount, sizeof(keepcount)) < 0) return -1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
int enableKeepalive(int fd)
|
|
|
|
|
{
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static bool CheckNetInfo()
|
|
|
|
|
{
|
|
|
|
|
QNetworkInterface net= QNetworkInterface::interfaceFromName("eth0");
|
|
|
|
|
if(net.flags().testFlag(QNetworkInterface::IsUp)
|
|
|
|
|
&& net.flags().testFlag(QNetworkInterface::IsRunning)
|
|
|
|
|
&& !net.flags().testFlag(QNetworkInterface::IsLoopBack)
|
|
|
|
|
&& (net.name() == "eth0"))
|
|
|
|
|
{
|
|
|
|
|
// qDebug() << "eth0 is Connected" << endl;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// qDebug() << "eth0 is Not Connected";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-11-21 20:28:23 +08:00
|
|
|
|
if_tcp::if_tcp()
|
|
|
|
|
{
|
2023-11-27 14:31:00 +08:00
|
|
|
|
this->connect_state = false;
|
|
|
|
|
this->timer_reconnect_ = nullptr;
|
|
|
|
|
this->tcp_socket_ = nullptr;
|
2023-12-29 09:41:37 +08:00
|
|
|
|
this->reconnect_timeout_ms = 3000;
|
2023-11-27 14:31:00 +08:00
|
|
|
|
this->cfg_ = syscfg();
|
|
|
|
|
|
|
|
|
|
this->timer_recv_end_ = nullptr;
|
|
|
|
|
this->recv_end_timeout_ms = 100;
|
|
|
|
|
qDebug("tcp created.");
|
2023-11-21 20:28:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if_tcp::~if_tcp()
|
|
|
|
|
{
|
2023-12-02 11:27:25 +08:00
|
|
|
|
if(timer_reconnect_!=nullptr){
|
|
|
|
|
delete timer_reconnect_;
|
|
|
|
|
}
|
|
|
|
|
if(tcp_socket_!=nullptr){
|
|
|
|
|
delete tcp_socket_;
|
|
|
|
|
}
|
|
|
|
|
if(timer_recv_end_!=nullptr){
|
|
|
|
|
delete timer_recv_end_;
|
|
|
|
|
}
|
2023-11-21 20:28:23 +08:00
|
|
|
|
}
|
2023-11-26 23:05:35 +08:00
|
|
|
|
|
|
|
|
|
void if_tcp::init()
|
|
|
|
|
{
|
2023-11-27 14:31:00 +08:00
|
|
|
|
if (nullptr == timer_reconnect_)
|
|
|
|
|
{
|
|
|
|
|
timer_reconnect_ = new QTimer(this);
|
|
|
|
|
connect(timer_reconnect_, &QTimer::timeout, this, &if_tcp::reconnect_cb);
|
|
|
|
|
}
|
|
|
|
|
timer_reconnect_->start(reconnect_timeout_ms);
|
|
|
|
|
if (nullptr == tcp_socket_)
|
|
|
|
|
{
|
|
|
|
|
tcp_socket_ = new QTcpSocket(this);
|
|
|
|
|
connect(tcp_socket_, SIGNAL(connected()), this, SLOT(connected_cb()));
|
|
|
|
|
connect(tcp_socket_, SIGNAL(disconnected()), this, SLOT(disconnected_cb()));
|
|
|
|
|
connect(tcp_socket_, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(state_changed_cb(QAbstractSocket::SocketState)));
|
|
|
|
|
connect(tcp_socket_, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(on_error_cb(QAbstractSocket::SocketError)));
|
|
|
|
|
connect(tcp_socket_, SIGNAL(readyRead()), this, SLOT(ready_read_cb()));
|
|
|
|
|
|
|
|
|
|
tcp_socket_->setSocketOption(QAbstractSocket::LowDelayOption, 1); // 禁用Nagle算法.
|
|
|
|
|
tcp_socket_->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
|
2023-12-29 09:41:37 +08:00
|
|
|
|
if (cfg_->tcp_enable){
|
2023-11-27 14:31:00 +08:00
|
|
|
|
tcp_socket_->connectToHost(QHostAddress(cfg_->server_ip), cfg_->server_port);
|
2023-12-29 09:41:37 +08:00
|
|
|
|
enableKeepalive(tcp_socket_->socketDescriptor());
|
|
|
|
|
}
|
2023-11-27 14:31:00 +08:00
|
|
|
|
}
|
2023-11-26 23:05:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取本机地址
|
|
|
|
|
QString if_tcp::get_local_ip()
|
|
|
|
|
{
|
2023-11-27 14:31:00 +08:00
|
|
|
|
QList<QNetworkInterface> network = QNetworkInterface::allInterfaces();
|
|
|
|
|
foreach (QNetworkInterface net, network)
|
|
|
|
|
{
|
|
|
|
|
QString netName = net.humanReadableName();
|
|
|
|
|
if (netName == "eth0")
|
2023-11-26 23:05:35 +08:00
|
|
|
|
{
|
2023-11-27 14:31:00 +08:00
|
|
|
|
QList<QNetworkAddressEntry> list = net.addressEntries(); // 获取IP地址与子掩码等
|
|
|
|
|
foreach (QNetworkAddressEntry address, list)
|
|
|
|
|
{
|
|
|
|
|
if (address.ip().protocol() == QAbstractSocket::IPv4Protocol) // 获取IPv4的地址
|
2023-11-26 23:05:35 +08:00
|
|
|
|
{
|
2023-11-27 14:31:00 +08:00
|
|
|
|
return address.ip().toString();
|
2023-11-26 23:05:35 +08:00
|
|
|
|
}
|
2023-11-27 14:31:00 +08:00
|
|
|
|
}
|
2023-11-26 23:05:35 +08:00
|
|
|
|
}
|
2023-11-27 14:31:00 +08:00
|
|
|
|
}
|
|
|
|
|
return QString();
|
2023-11-26 23:05:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void if_tcp::reconnect_cb()
|
|
|
|
|
{
|
2023-12-29 09:41:37 +08:00
|
|
|
|
// 网线拔出之后自动断开连接
|
|
|
|
|
if(CheckNetInfo()==false){
|
|
|
|
|
if(connect_state!=false){
|
|
|
|
|
connect_state=false;
|
|
|
|
|
tcp_socket_->close();
|
2023-11-27 14:31:00 +08:00
|
|
|
|
}
|
2023-12-29 09:41:37 +08:00
|
|
|
|
}else{
|
|
|
|
|
if (connect_state != true)
|
2023-11-27 14:31:00 +08:00
|
|
|
|
{
|
|
|
|
|
if (cfg_->tcp_enable)
|
|
|
|
|
{
|
2023-12-29 09:41:37 +08:00
|
|
|
|
tcp_socket_->connectToHost(QHostAddress(cfg_->server_ip), cfg_->server_port);
|
2023-11-27 14:31:00 +08:00
|
|
|
|
}
|
2023-11-26 23:05:35 +08:00
|
|
|
|
}
|
2023-11-27 14:31:00 +08:00
|
|
|
|
}
|
2023-11-26 23:05:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void if_tcp::connected_cb()
|
|
|
|
|
{
|
2023-11-27 14:31:00 +08:00
|
|
|
|
connect_state = true;
|
|
|
|
|
emit tcp_connected_signal();
|
|
|
|
|
qInfo("connected");
|
2023-11-26 23:05:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void if_tcp::disconnected_cb()
|
|
|
|
|
{
|
2023-11-27 14:31:00 +08:00
|
|
|
|
connect_state = false;
|
|
|
|
|
qInfo("disconnected");
|
2023-11-26 23:05:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void if_tcp::state_changed_cb(QAbstractSocket::SocketState nSocketState)
|
|
|
|
|
{
|
2023-12-29 09:41:37 +08:00
|
|
|
|
// qInfo("state changed:%d", nSocketState);
|
2023-11-26 23:05:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void if_tcp::on_error_cb(QAbstractSocket::SocketError nErrCode)
|
|
|
|
|
{
|
2023-11-27 14:31:00 +08:00
|
|
|
|
connect_state = false;
|
2023-12-29 09:41:37 +08:00
|
|
|
|
// qWarning("on error:%d", nErrCode);
|
2023-11-26 23:05:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void if_tcp::ready_read_cb()
|
|
|
|
|
{
|
2023-11-27 14:31:00 +08:00
|
|
|
|
QByteArray data = tcp_socket_->readAll();
|
|
|
|
|
if (irq_fun)
|
|
|
|
|
{
|
|
|
|
|
irq_fun(myarray(data));
|
|
|
|
|
}
|
2023-12-29 09:41:37 +08:00
|
|
|
|
emit tcp_recv_signal();
|
|
|
|
|
// qInfo()<< "recv data from tcp:"<<crc::byte_array_to_string(recv)<<endl;
|
2023-11-26 23:05:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int if_tcp::write(myarray data)
|
|
|
|
|
{
|
2023-12-29 09:41:37 +08:00
|
|
|
|
emit tcp_send_signal();
|
2023-11-27 14:31:00 +08:00
|
|
|
|
if (nullptr == tcp_socket_ || false == connect_state)
|
|
|
|
|
{
|
|
|
|
|
// qWarning() << "Can’t send data , TcpClient socket not connect.";
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
int wb = tcp_socket_->write(data);
|
|
|
|
|
if (!tcp_socket_->flush())
|
|
|
|
|
{
|
|
|
|
|
qWarning("write fial:[%s]", data.toHex(' ').data());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
return wb;
|
2023-11-26 23:05:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
InterFace *if_tcp_get()
|
|
|
|
|
{
|
2023-11-27 14:31:00 +08:00
|
|
|
|
static InterFace *if_ = nullptr;
|
|
|
|
|
if (if_ == nullptr)
|
|
|
|
|
{
|
|
|
|
|
if_ = new if_tcp();
|
|
|
|
|
QTimer::singleShot(0, if_, &InterFace::init);
|
|
|
|
|
}
|
|
|
|
|
return if_;
|
2023-11-26 23:05:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-11-27 14:31:00 +08:00
|
|
|
|
if_export(tcp, if_tcp_get);
|