QT socket TCP通信程序模板--服務端

TCP通信,要區分服務端,和客戶端。

服務端的功能是,設置要監聽的端口,然後等待客戶端發起的連接。

 

 

QT中TCP服務器端的編程步驟:

(1)new一個TCP服務器 QTcpServer
(2)進入listen監聽狀態(形參爲:要監聽的IP,一般填Any, 要監聽的端口號)
(3)一旦有客戶端申請接入,服務端會產生消息QTcpServer::newConnection,在消息的處理函數中,記錄下客戶端發起的socket連接QTcpSocket(一般要用鏈表數據結構記錄,因爲可能會有多個客戶端要接入)。

(4)把剛纔記錄下的socket的【已連接】、【連接已斷開】、【收到數據】3個常用的信號槽寫好。(這一步驟和客戶端編程是一樣的,請參考我的另一篇博客《QT socket TCP通信程序模板- 客戶端》)

(5)發送數據用QTcpSocket::write(uint8_t *bug, int65_t maxLen);

示例代碼:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>
#include <QHostAddress>
#include <QMap>
#include <QByteArray>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_ptnCreateTcp_clicked();

    void on_ptnSend_clicked();
    void when_tcp_newConnection(void);
    void when_tcpClientDisconnected(void);
    void when_receivedData(void);

private:
    Ui::MainWindow *ui;
    QTcpServer *tcpServer;
    QList<QTcpSocket*> tcpSktList;

};

#endif // MAINWINDOW_H


#include "mainwindow.h"
#include "ui_mainwindow.h"

#define debug_print(str) ui->textEditDebug->append(str)

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    tcpServer = new QTcpServer();
    connect(tcpServer, SIGNAL(newConnection()), this, SLOT(when_tcp_newConnection()));



    for(int i = 0; i < ui->tableClients->rowCount(); i++)
    {
        ui->tableClients->setItem(i, 0, new QTableWidgetItem("無IP"));
        ui->tableClients->setItem(i, 1, new QTableWidgetItem("無端口"));
        ui->tableClients->setItem(i, 2, new QTableWidgetItem("未連接"));

    }
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_ptnCreateTcp_clicked()//TCP服務器進入監聽狀態
{
    uint16_t port = ui->spinPort->value();
    tcpServer->close();//若listen時,想更換監聽的端口號,必須先close掉

    tcpServer->listen(QHostAddress::Any, port);
    debug_print(QString("正在監聽本機IP的第%1端口").arg(port));

}

void MainWindow::on_ptnSend_clicked()
{

}

void MainWindow::when_tcp_newConnection()
{
    debug_print("有TCP客戶端請求連接");
    QTcpSocket *tcpSocket = tcpServer->nextPendingConnection();//新的客戶端發起的連接
    QHostAddress clientIp = tcpSocket->peerAddress();//客戶端的IP
    quint16 port = tcpSocket->peerPort();//客戶端的端口
    if(tcpSktList.contains(tcpSocket))
    {
        debug_print(QString("%1:%2的連接早已建立過").arg(clientIp.toString()).arg(port));
    }
    else
    {
        debug_print("新的連接已建立");
        tcpSktList.append(tcpSocket);//記錄下客戶端發起的連接
        connect(tcpSocket, SIGNAL(disconnected()), this, SLOT(when_tcpClientDisconnected()));//客戶端掉線處理
        connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(when_receivedData()));//客戶端發來的數據處理

    }

//    ui->tableClients->item(0,0)->setText(clientIp.toString());//
//    ui->tableClients->item(0,1)->setText(QString::number(port));


}

void MainWindow::when_tcpClientDisconnected(void)
{
    debug_print("tcp客戶端掉線");
    QTcpSocket *tcpSocket = static_cast<QTcpSocket *>( QObject::sender() );
    tcpSktList.removeOne(tcpSocket);
}

void MainWindow::when_receivedData()
{
    QTcpSocket *tcpSocket = static_cast<QTcpSocket *>( QObject::sender() );
    qDebug() <<QString("收到來自客戶端%1的消息:").arg(tcpSocket->peerAddress().toString());

    QByteArray ba = tcpSocket->readAll();
    qDebug() << ba;//打印收到的來自客戶端的消息
}





 

服務器端的TCP程序,不需要本機的IP地址,listen時,只填端口號即可。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章