1. 程式人生 > >QT網路程式設計例項

QT網路程式設計例項

最終效果圖:

--------------------------------------------------------------------------------------------------------

注意:建好工程後在“.pro”檔案中加上“Qt += network”

--------------------------------------------------------------------------------------------------------

服務端:

GUI介面設計:

--------------------------------------------------------------------------------------------------------

實現程式碼:

#ifndef MAINWINDOW_H

#define MAINWINDOW_H

 

#include <QMainWindow>

#include<QtNetwork>

#include<QtNetwork/QTcpSocket>

#include<QtNetwork/QTcpServer>

#include <QTimer>

namespace Ui {

   class MainWindow;

}

 

class MainWindow : public QMainWindow

{

   Q_OBJECT

 

public:

   explicit MainWindow(QWidget *parent = 0);

   ~MainWindow();

protected:

void init();        //初始化函式用於完成一些諸如建立訊號與槽之間的聯絡和變數給初值的初始化工作。

     

private slots:

   void on_send_clicked();

   void newListen(); //建立TCP監聽事件

   void acceptConnection(); //接受客戶端連線

   void displayError(QAbstractSocket::SocketError); //顯示錯誤資訊

private:

   Ui::MainWindow *ui;

   QTcpSocket *tcpSocket;

   QTcpServer *tcpServer;

};

#endif // MAINWINDOW_H

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include "mainwindow.h"

#include "ui_mainwindow.h"

 

MainWindow::MainWindow(QWidget *parent) :

   QMainWindow(parent),

   ui(new Ui::MainWindow)

{

   ui->setupUi(this);

    init();

}

 

void MainWindow::init()

{

   timer = new QTimer;

   send_flag = 0;

 

  this->tcpServer = new QTcpServer(this);

  this->tcpSocket = new QTcpSocket(this);

 

  newListen();

  connect(tcpServer,SIGNAL(newConnection()),this,SLOT(acceptConnection()));

  //newConnection()用於當有客戶端訪問時發出訊號,acceptConnection()訊號處理函式

  connect(tcpSocket,SIGNAL(error(QAbstractSocket::SocketError)),

              this,SLOT(displayError(QAbstractSocket::SocketError)));

 //當tcpSocket在接受客戶端連線時出現錯誤時,displayError(QAbstractSocket::SocketError)進行錯誤提醒並關閉tcpSocket。

 

}

 

void MainWindow::on_send_clicked()

{

   this->tcpSocket->write(ui->lineEdit->text().toLatin1());

    //用於傳送字元訊息

}

 

void MainWindow::newListen()

{

     //監聽是否有客戶端來訪,且對任何來訪者監聽,埠為6666

   if(!tcpServer->listen(QHostAddress::Any,6666))

   {

      qDebug()<<tcpServer->errorString();

      close();

      return;

   }

}

 

void MainWindow::acceptConnection()

{

     //當有客戶來訪時將tcpSocket接受tcpServer建立的socket

  tcpSocket = tcpServer->nextPendingConnection();

}

 

void MainWindow::displayError(QAbstractSocket::SocketError)

{

   qDebug()<<tcpSocket->errorString();

   tcpSocket->close();

}

 

MainWindow::~MainWindow()

{

   delete ui;

}

--------------------------------------------------------------------------------------------------------

客服端:

GUI介面設計:

--------------------------------------------------------------------------------------------------------

實現程式碼:

#ifndef MAINWINDOW_H

#define MAINWINDOW_H

 

#include <QMainWindow>

#include<QtNetwork>

#include<QtNetwork/QTcpSocket>

 

namespace Ui {

   class MainWindow;

}

 

class MainWindow : public QMainWindow

{

   Q_OBJECT

 

public:

   explicit MainWindow(QWidget *parent = 0);

   ~MainWindow();

 

protected:

   void init();

   void newTCPConnect();//用於建立服務端與客戶之間的連線函式

private:

   Ui::MainWindow *ui;

   QTcpSocket *tcpSocket;

private slots:

   void revData(); //接收來自服務端的資料

   void displayError(QAbstractSocket::SocketError);

};

 

#endif // MAINWINDOW_H

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include "mainwindow.h"

#include "ui_mainwindow.h"

 

MainWindow::MainWindow(QWidget *parent) :

   QMainWindow(parent),

   ui(new Ui::MainWindow)

{

   ui->setupUi(this);

 

   init();

}

 

void MainWindow::init()

{

   this->tcpSocket = new QTcpSocket(this);

 

   newTCPConnect();

       //這裡我是採用程式啟動就自訪問服務端(也可根據實際情況採用手動連線手動輸入服務端ip的方式。)

   connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(revData()));

     //readyRead()表示服務端傳送資料過來即發動訊號,接著revData()

   進行處理。

   connect(tcpSocket,SIGNAL(error(QAbstractSocket::SocketError)),

           this,SLOT(displayError(QAbstractSocket::SocketError)));

}

 

void MainWindow::revData()

{

   QString datas = tcpSocket->readAll();

//接收字串資料。

   ui->lineEdit->setText(datas);

     //顯示字串資料。

}

 

void MainWindow::newTCPConnect()

{

   tcpSocket->abort();

   tcpSocket->connectToHost("127.0.0.1",6666);

      //這裡可以根據實際情況在使用者介面上進行輸入。

}

 

void MainWindow::displayError(QAbstractSocket::SocketError)

{

   qDebug()<<tcpSocket->errorString();

   tcpSocket->close();

}

 

MainWindow::~MainWindow()

{

   delete ui;

}

--------------------------------------------------------------------------------------------------------

最終效果圖:

--------------------------------------------------------------------------------------------------------

注意:圖片傳送大體流程同《Qt網路程式設計—TCP/IP(一)》只是在傳送時這裡採用

資料流QDataStream形式。因為使用攝像進行監控時也是對一幀一幀的圖片進

行處理,因此掌握瞭如何用Qt網路實現圖片傳輸基本就可以實現遠端實時監控。

--------------------------------------------------------------------------------------------------------

服務端:

GUI介面設計:

--------------------------------------------------------------------------------------------------------

實現程式碼:

#include<QtNetwork>
#include<QtNetwork/QTcpServer>
#include<QtNetwork/QTcpSocket>
#include<QImage>
#include<QTimer>

namespace Ui {
    class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

    QImage *image;
    QTimer *timer;

protected:
    void init();
    void displayvideo();

private:
    Ui::MainWindow *ui;
    QTcpSocket *tcpSocket;
    QTcpServer *tcpServer;

private slots:
    void newListen();
    void acceptConnection();
    void displayError(QAbstractSocket::SocketError);
    void on_send_clicked();
    void sendData();
};

#endif // MAINWINDOW_H

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

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

int count = 1;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    init();
}

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

void MainWindow::init()
{
   this->tcpServer = new QTcpServer(this);
   this->tcpSocket = new QTcpSocket(this);

   timer = new QTimer;

   newListen();

   connect(timer,SIGNAL(timeout()),this,SLOT(sendData()));
   connect(tcpServer,SIGNAL(newConnection()),this,SLOT(acceptConnection()));
   connect(tcpSocket,SIGNAL(error(QAbstractSocket::SocketError)),
           this,SLOT(displayError(QAbstractSocket::SocketError)));


}

void MainWindow::newListen()
{
    if(!tcpServer->listen(QHostAddress::Any,6666))
    {
       qDebug()<<tcpServer->errorString();
       close();
       return;
    }
}

void MainWindow::acceptConnection()
{
   tcpSocket = tcpServer->nextPendingConnection();
}

void MainWindow::displayError(QAbstractSocket::SocketError)
{
    qDebug()<<tcpSocket->errorString();
    tcpSocket->close();
}

void MainWindow::on_send_clicked()
{
    timer->start(300);
    //sendData();
}

void MainWindow::sendData()
{
    //timer->stop();
    QByteArray Data;
    QBuffer buffer;
    QDataStream out(&Data,QIODevice::WriteOnly);

    displayvideo();
    image->save(&buffer,"jpg");

   //這裡在傳送一張圖片時必須先將圖片大小資訊寫入待發送資料流中在將JPG格式圖片寫入資料流這樣可以 

   //確保客 戶端能正確接收一張完整圖片。

   out.setVersion(QDataStream::Qt_4_6);
    out<<(quint32)buffer.data().size();
    Data.append(buffer.data());

    tcpSocket->write(Data);

    delete image;
    Data.resize(0);
    buffer.reset();

   // timer->start(100);

}

void MainWindow::displayvideo()
{
    FILE *fp;
    char file[105776] = {0};
    char name[10] = {0};

    sprintf(name,"tu/%d.jpg",count++);

    fp = fopen(name,"rb");
    fread(&file,105776,1,fp);
    fclose(fp);

    if(count == 11) count = 1;

    image = new QImage((unsigned char*)file,0,0,QImage::Format_RGB16);
    image->loadFromData((unsigned char*)file,105776);

    ui->label->setScaledContents(true);
    ui->label->setPixmap(QPixmap::fromImage(*image,Qt::AutoColor));
}

--------------------------------------------------------------------------------------------------------

客服端:

GUI介面設計:

--------------------------------------------------------------------------------------------------------

實現程式碼:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include<QMainWindow>
#include<QtNetwork>
#include<QtNetwork/QTcpSocket>
#include<QImage>
#include<QImageReader>

namespace Ui {
    class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

protected:
    void init();
    void newTCPConnect();
    void displayvideo();

private:
    Ui::MainWindow *ui;
    QTcpSocket *tcpSocket;
private slots:
    void revData();
    void displayError(QAbstractSocket::SocketError);
};

#endif // MAINWINDOW_H

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

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

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    init();
}

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

void MainWindow::init()
{

    tcpSocket = new QTcpSocket(this);

    datasize = 0;

    newTCPConnect();
    connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(revData()));
    connect(tcpSocket,SIGNAL(error(QAbstractSocket::SocketError)),
            this,SLOT(displayError(QAbstractSocket::SocketError)));
}

void MainWindow::newTCPConnect()
{
    tcpSocket->abort();
    tcpSocket->connectToHost(QHostAddress::Any,6666);
}

void MainWindow::revData()
{

    //客服端第一次先接收資料流中圖片大小資訊
    if(datasize == 0)
    {
        QDataStream in(tcpSocket);
        in.setVersion( QDataStream::Qt_4_6);

        if(tcpSocket->bytesAvailable() < sizeof(quint32))
        {
          return;
        }

        in>>datasize;
    }

   //然後根據圖片大小資訊接收JPG格式圖片

    if(datasize > tcpSocket->bytesAvailable())
    {
        return;
    }

    //顯示接收到的圖片
    displayvideo();
}

void MainWindow::displayvideo()
{
    QByteArray Data = tcpSocket->read(datasize);
    QBuffer buffer(&Data);
    buffer.open( QIODevice::ReadOnly);

    QImageReader reader(&buffer, "jpg");
    QImage image = reader.read();

    ui->label->setScaledContents(true);
    ui->label->setPixmap(QPixmap::fromImage(image,Qt::AutoColor));

    if(datasize != 0) ui->label_2->setText(QString::number(datasize));

    //將datasize圖片大小資訊重置0為下一接收做準備。

    datasize = 0;
}

void MainWindow::displayError(QAbstractSocket::SocketError)
{
    qDebug()<<tcpSocket->errorString();
    tcpSocket->close();
}

最終效果圖:

--------------------------------------------------------------------------------------------------------

注意:此處只有服務端採用了多執行緒,即可以接收多個客戶端的訪問並進行相互

信。這裡在使用時必須先啟動服務端再啟動客戶端,此時在服務端的左側方框

內會顯示與服務端連線的客戶端名。滑鼠點選你想要通訊的客戶名然後在傳送消

息即可。

--------------------------------------------------------------------------------------------------------

服務端:

GUI介面設計:

--------------------------------------------------------------------------------------------------------

實現程式碼:

非執行緒部分:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include<QMainWindow>
#include<QtNetwork/QTcpServer>
#include<QStandardItemModel>
#include"socketthread.h"

namespace Ui {
    class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

    QStandardItemModel *model;

protected:
    void init();
    void newListen();

private:
    Ui::MainWindow *ui;
    QTcpServer *tcpServer;

signals:
   void sendToSocketThrd(QString client,QString datas);

private slots:
    void createSocketThread();
    void revFromThrd(bool isClient,QString datas);
    void removeClient(QString client);
    //void addSocketDescription(int socketdescription);
    //void removeSocketDescription(int socketdescription);
    void on_send_clicked();

    void on_friendlist_clicked(QModelIndex index);
};

#endif // MAINWINDOW_H

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

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

int Des[256] = {0};
int clientNum = 0;
QString currentClient;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    init();
}

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

void MainWindow::init()
{
    tcpServer = new QTcpServer;
    model     = new QStandardItemModel();

    model->setColumnCount(2);
    model->setHeaderData(0,Qt::Horizontal,"NAME");
    model->setHeaderData(1,Qt::Horizontal,"IP");

    connect(tcpServer,SIGNAL(newConnection()),this,SLOT(createSocketThread()));

    ui->friendlist->setModel(model);
    ui->friendlist->hideColumn(1);
    ui->friendlist->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);

    ui->friendlist->setEditTriggers(QAbstractItemView::NoEditTriggers);

    newListen();
}

void MainWindow::newListen()
{
    if(!tcpServer->listen(QHostAddress::Any,6666))
    {
        qDebug()<<tcpServer->errorString();
        tcpServer->close();
        return ;
    }
}

void MainWindow::createSocketThread()
{
    socketThread *SThread = new socketThread(tcpServer->nextPendingConnection());

    connect(SThread,SIGNAL(sendToMainWin(bool,QString)),this,SLOT(revFromThrd(bool,QString)));
    connect(SThread,SIGNAL(closeClient(QString)),this,SLOT(removeClient(QString)));
    //connect(SThread,SIGNAL(sendSocketDescription(int)),this,SLOT(addSocketDescription(int)));
    //connect(SThread,SIGNAL(closeSocketDescription(int)),this,SLOT(removeSocketDescription(int)));
    connect(this,SIGNAL(sendToSocketThrd(QString,QString)),SThread,SLOT(revFromMainWin(QString,QString)));

    SThread->start();
}

void MainWindow::on_send_clicked()
{
    QString message;

    message = "SERVER\n"+ui->message->document()->toPlainText();
    ui->message->clear();

    emit sendToSocketThrd(currentClient,message);
}
/*
void MainWindow::addSocketDescription(int socketdescription)
{
    for(int i = 0; i < 256; i++)
    {
        if(Des[i] == 0)
        {
            Des[i] = socketdescription;
            break;
        }
    }
}

void MainWindow::removeSocketDescription(int socketdescription)
{
    for(int i = 0; i < 256; i++)
    {
        if(Des[i] == socketdescription)
        {
            Des[i] = 0;
            break;
        }
    }
}

*/
void MainWindow::revFromThrd(bool isClient,QString datas)
{
    if(isClient)
    {
        QString tmp;
        tmp = QString(strtok(datas.toLatin1().data(),"\n"));
        model->setItem(clientNum,0,new QStandardItem(tmp));
        tmp = QString(strstr(datas.toLatin1().data(),"\n")).mid(1);
        model->setItem(clientNum,1,new QStandardItem(tmp));
        clientNum++;
    }
    else
    {
        ui->displaymessage->append(datas);
    }
}

void MainWindow::removeClient(QString client)
{
    for(int i = 0; i < clientNum;i++)
    {
        if(model->item(i)->text().operator ==(client))
        {
            model->removeRow(i);
            clientNum--;
            break;
        }
    }
}

void MainWindow::on_friendlist_clicked(QModelIndex index)
{
    currentClient = index.data().toString()+"\n";
    currentClient += index.sibling(index.row(),1).data().toString();
}


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

執行緒部分:

#ifndef SOCKETTHREAD_H
#define SOCKETTHREAD_H

#include<QThread>
#include<QtNetwork/QTcpSocket>
#include<QtNetwork/QHostAddress>

class socketThread : public QThread
{
    Q_OBJECT
public:
    explicit socketThread(QObject *parent = 0);
    socketThread(QTcpSocket *socket);

    QString ip;
    QString clientName;
    bool isClient;
    int  description;

protected:
    void run();

signals:
    void sendToMainWin(bool isClient,QString datas);
    void sendSocketDescription(int socketDescription);
    void closeClient(QString client);

private slots:
    void revFromMainWin(QString client,QString datas);
    void closeSocket();
    void revDatas();

private:
    QTcpSocket * tcpSocket;

};

#endif // SOCKETTHREAD_H


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include "socketthread.h"

socketThread::socketThread(QObject *parent) :
    QThread(parent)
{
}

socketThread::socketThread(QTcpSocket *socket)
{
    tcpSocket   = socket;
    isClient    = true;
    description = tcpSocket->socketDescriptor();
    ip          = tcpSocket->peerAddress().toString();

    connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(revDatas()));
}

void socketThread::run()
{
    connect(tcpSocket,SIGNAL(disconnected()),this,SLOT(closeSocket()));
}

void socketThread::revDatas()
{
    if(isClient)
    {
        clientName = tcpSocket->readAll();
        emit sendToMainWin(isClient,clientName+"\n"+ip);
        isClient = false;
    }
    else
    {
        emit sendToMainWin(isClient,clientName+"\n"+tcpSocket->readAll());
    }
}

void socketThread::revFromMainWin(QString client,QString datas)
{
    QString tmp = clientName+"\n"+ip;

    if(tmp.operator ==(client))
    {
        tcpSocket->write(datas.toLatin1().data());
    }
}

void socketThread::closeSocket()
{
    emit closeClient(clientName);
    tcpSocket->close();
}

--------------------------------------------------------------------------------------------------------

服務端:

GUI介面設計:

--------------------------------------------------------------------------------------------------------

實現程式碼:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include<QtNetwork>
#include<QtNetwork/QTcpSocket>

namespace Ui {
    class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

    QString myName;

protected:
    void init();
    void newTCPConnect();

private:
    Ui::MainWindow *ui;
    QTcpSocket *tcpSocket;

private slots:
    void revData();
    void sendMyName();
    void displayError(QAbstractSocket::SocketError);
    void on_send_clicked();
};

#endif // MAINWINDOW_H


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include<QtNetwork>
#include<QtNetwork/QTcpSocket>

namespace Ui {
    class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

    QString myName;

protected:
    void init();
    void newTCPConnect();

private:
    Ui::MainWindow *ui;
    QTcpSocket *tcpSocket;

private slots:
    void revData();
    void sendMyName();
    void displayError(QAbstractSocket::SocketError);
    void on_send_clicked();
};

#endif // MAINWINDOW_H