Qt實現(xiàn)TCP客戶端和服務(wù)器通訊程序
復(fù)習(xí)的心態(tài)過一遍之前基礎(chǔ)的一些東西,Qt封裝了QTcpServer和QTcpSocket兩個類,其中QTcpServer繼承自QObject,通過listen()函數(shù)監(jiān)聽傳入的客戶端連接,當(dāng)Client連接上時,QTcpServer會發(fā)出newConnection的信號,在對應(yīng)的槽函數(shù)中使用nextPendingConnection()拿到連接的客戶端的句柄和信息。
而QTcpSocket則是讀寫數(shù)據(jù)的時候使用,過程很簡單。
服務(wù)器流程:listen->newConnection->nextPendingConnection->readAll/write
客戶端流程:connectToHost->waitForConnected->write/readAll
需要注意的是在使用網(wǎng)絡(luò)相關(guān)的類前,需要在pro文件加上QT += network
通信時:
客戶端掉線時:
QTcpServer服務(wù)器代碼(包含.h和.cpp):
.h
#ifndef WIDGET_H #define WIDGET_H ? #include <QWidget> #include <QTcpServer> #include <QTcpSocket> ? QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACE ? class Widget : public QWidget { ? ? Q_OBJECT ? public: ? ? Widget(QWidget *parent = nullptr); ? ? ~Widget(); ? protected slots: ? ? void onSendBtnClicked(); ? ? void onNewClientConnected(); ? ? void onRecvData(); ? ? void onClientDisconnected(); ? private: ? ? void Init(); ? private: ? ? Ui::Widget *ui; ? private: ? ? QTcpServer *_tcpServer; ? ? QTcpSocket *_tcpSocket; }; #endif // WIDGET_H
.cpp
#include "widget.h" #include "ui_widget.h" #include <QHostAddress> #include <QDebug> ? #define MyTcpPort 8886 ? Widget::Widget(QWidget *parent) ? ? : QWidget(parent) ? ? , ui(new Ui::Widget) ? ? ,_tcpServer(nullptr) ? ? ,_tcpSocket(nullptr) { ? ? ui->setupUi(this); ? ? ? connect(this->ui->btn_send,&QPushButton::clicked,this,&Widget::onSendBtnClicked); ? ? ? Init(); ? ? ? setWindowTitle("服務(wù)端"); } ? Widget::~Widget() { ? ? delete ui; ? ? ? if(_tcpSocket) ? ? { ? ? ? ? _tcpSocket->disconnect(); ? ? ? ? _tcpSocket->abort(); ? ? ? ? _tcpSocket->close(); ? ? ? ? _tcpSocket->deleteLater(); ? ? } ? ? if(_tcpServer) ? ? { ? ? ? ? _tcpServer->close(); ? ? ? ? delete _tcpServer; ? ? } } ? void Widget::Init() { ? ? _tcpSocket = new QTcpSocket; ? ? _tcpServer = new QTcpServer; ? ? ? int ret = _tcpServer->listen(QHostAddress::AnyIPv4,MyTcpPort); ? ? if(ret==0) ? ? { ? ? ? ? qDebug()<<"_tcpServer->listen is failied"; ? ? ? ? return; ? ? } ? ? connect(_tcpServer,&QTcpServer::newConnection,this,&Widget::onNewClientConnected); } ? void Widget::onSendBtnClicked() { ? ? if(!_tcpSocket) return; ? ? ? QString inputText = ui->inputEdit->text(); ? ? if(inputText.isEmpty()) ? ? ? ? return; ? ? //發(fā)送數(shù)據(jù) ? ? int ret = _tcpSocket->write(inputText.toStdString().c_str()); ? ? if(ret<0) ? ? { ? ? ? ? qDebug()<<"write to client is failed!"; ? ? } } ? void Widget::onNewClientConnected() { ? ? if(_tcpServer->hasPendingConnections()) ? ? { ? ? ? ? _tcpSocket = _tcpServer->nextPendingConnection(); ? ? ? ? if(!_tcpSocket->isValid()) return; ? ? ? ? connect(_tcpSocket,&QTcpSocket::readyRead,this, ? ? ? ? ? ? ? ? &Widget::onRecvData); ? ? ? ? connect(_tcpSocket,&QTcpSocket::disconnected,this, ? ? ? ? ? ? ? ? &Widget::onClientDisconnected); ? ? } } ? void Widget::onRecvData() { ? ? if(!_tcpSocket) return; ? ? QString recvData=_tcpSocket->readAll(); ? ? qDebug()<<"recvData:"<<recvData; ? ? ? this->ui->recvEdit->append(recvData); } ? void Widget::onClientDisconnected() { ? ? QString clientIp = _tcpSocket->peerAddress().toString(); ? ? this->ui->recvEdit->append(clientIp+" is Drop line!"); }
QTcpClient客戶端代碼(包含.h和.cpp):
/.h
#ifndef WIDGET_H #define WIDGET_H ? #include <QWidget> #include <QTcpSocket> ? QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACE ? class Widget : public QWidget { ? ? Q_OBJECT ? public: ? ? Widget(QWidget *parent = nullptr); ? ? ~Widget(); ? private: ? ? void Init(); ? protected slots: ? ? void onSendBtnClicked(); ? ? void onRecvData(); ? private: ? ? Ui::Widget *ui; ? private: ? ? QTcpSocket *_tcpClient; }; #endif // WIDGET_H ? /.cpp #include "widget.h" #include "ui_widget.h" ? #define MyTcpPort 8886 ? Widget::Widget(QWidget *parent) ? ? : QWidget(parent) ? ? , ui(new Ui::Widget),_tcpClient(nullptr) { ? ? ui->setupUi(this); ? ? ? connect(this->ui->btn_send,&QPushButton::clicked,this,&Widget::onSendBtnClicked); ? ? ? Init(); ? ? ? ?setWindowTitle("客戶端"); } ? Widget::~Widget() { ? ? delete ui; ? ? ? if(_tcpClient) ? ? { ? ? ? ? _tcpClient->close(); ? ? ? ? _tcpClient->deleteLater(); ? ? } } ? void Widget::Init() { ? ? _tcpClient=new QTcpSocket; ? ? _tcpClient->abort(); ? ? _tcpClient->connectToHost("127.0.0.1",MyTcpPort); ? ? if(!_tcpClient->waitForConnected(2000)) ? ? { ? ? ? ? qDebug()<<"connect is failed!"; ? ? ? ? return; ? ? } ? ? qDebug()<<"connect is successful"; ? ? connect(_tcpClient,&QTcpSocket::readyRead,this,&Widget::onRecvData); } ? void Widget::onSendBtnClicked() { ? ? if(!_tcpClient) return; ? ? ? QString wStr=ui->inputEdit->text(); ? ? ? int ret = _tcpClient->write(wStr.toStdString().c_str()); ? ? if(ret<0) ? ? { ? ? ? ? qDebug()<<"send data is failed"; ? ? } ? ? qDebug()<<"send data is successful!"; } ? void Widget::onRecvData() { ? ? if(!_tcpClient) return; ? ? ? QString recvData= _tcpClient->readAll(); ? ? ui->recvEdit->append(recvData); ? ? qDebug()<<"recvData:"<<recvData; }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C++文件相關(guān)函數(shù)CreateFile|ReadFile|WriteFile用法詳解
這篇文章主要為大家詳細介紹了c++有關(guān)文件創(chuàng)建、讀取和寫入的api:CreateFile、ReadFile、WriteFile的具體使用,需要的可以參考下2023-04-04基于Windows API實現(xiàn)遍歷所有文件并刪除的方法
這篇文章主要介紹了基于Windows API實現(xiàn)遍歷所有文件并刪除的方法,是win32應(yīng)用程序的一個比較典型的文件操作應(yīng)用技巧,需要的朋友可以參考下2015-04-04