qt 作为桌面应用本来不应该用来做 tcp server的,但是架不住甲方的需求太奇葩,只能忍了。
第一版:
// 初始化
{
...
m_pTcpServer = new QTcpServer(this);
connect(m_pTcpServer, &QTcpServer::newConnection, this, &tcpSer::ConnCli);
connect(m_pTcpServer, &QTcpServer::acceptError, this, &tcpSer::displayError);
...
}
// 客户端连接后起线程读写数据
void tcpSer::ConnCli()
{
//获取与客户端通信的socket
QTcpSocket* pClientConnection = m_pTcpServer->nextPendingConnection();
//从客户端读数据
// QString key = pClientConnection->peerAddress().toString() + pClientConnection->peerPort();
m_pCliVec.append(pClientConnection);
std::thread cliThread = std::thread(&tcpSer::cliThread, this, pClientConnection);
cliThread.detach();
}
// 读写连接的客户端数据
void tcpSer::cliThread(QTcpSocket* cli)
{
QString key = cli->peerAddress().toString() + cli->peerPort();
qDebug() << "tcpSer::client conn " << key;
bool loop = true;
connect(cli, &QTcpSocket::disconnected, this, [&]{
loop = false;
});
connect(cli, &QIODevice::readyRead, this, [&](){
QByteArray recvMsg = cli->readAll();
if(recvMsg.size() == 0){
return;
}
commHandle(recvMsg.toStdString());
});
while(loop){
QThread::sleep(5);
}
qDebug() << "tcpSer::client disconn " << key;
pthread_detach(pthread_self());
}
存在的问题:
readyRead 当有连续数据的时候,只触发一次,导致接收多个数据单只读了一包,后面再来数据之后,又形成了粘包。
第二版:
void tcpSer::cliThread(QTcpSocket* cli)
{
QString key = cli->peerAddress().toString() + cli->peerPort();
qDebug() << "tcpSer::client conn " << key;
bool loop = true;
connect(cli, &QTcpSocket::disconnected, this, [&]{
loop = false;
});
while(loop){
if(!iotConn->waitForConnected(1000)){
std::cout<< "reconnect iotHub" << std::endl;
}
if(iotConn->waitForReadyRead(1000) == false){
continue;
}
QByteArray recvMsg = iotConn->readAll();
commHandle(recvMsg.toStdString());
}
qDebug() << "tcpSer::client disconn " << key;
pthread_detach(pthread_self());
}
问题更可怕,当客户端连上发了一包数据马上断开后,直接程序段错误挂了。
最终版:
void tcpSer::cliThread(QTcpSocket* cli)
{
QString key = cli->peerAddress().toString() + cli->peerPort();
qDebug() << "tcpSer::client conn " << key;
bool loop = true;
connect(cli, &QTcpSocket::disconnected, this, [&]{
loop = false;
});
while(loop){
QByteArray recvInfo = cli->read(BUFF_SIZE);
if(recvInfo.size() == 0){
QThread::msleep(100);
continue;
}
m_DataRecv.append(recvInfo);
commHandle(recvMsg.toStdString());
}
qDebug() << "tcpSer::client disconn " << key;
pthread_detach(pthread_self());
}
最终版暴力断开连接多次,都抗住了,没有发生异常。