天天看點

lesson13-網絡程式設計

一、QHttp

1、QT的應用層協定

QT為網絡操作提供了自己封裝的類,例如QFtp和QHttp就提供了應用層的檔案傳輸

QHttp類用于建構http用戶端程式,它提供了很多操作,例如最常用的get和post函數。Qhttp采用的是一步工作的方式,當調用的get或者post函數之後會立即傳回,這樣會加快圖形界面的響應

2、建構http下載下傳程式

http下載下傳自然離不開QHttp類,在Qt的網絡操作中需要在工程檔案中加一句話:QT+=network,否則網絡操作會失敗的

QHttp的get方法可以讓使用者從伺服器上擷取資料,get方法需要提供下載下傳的路徑和檔案。

在http互動的過程中主要有幾個信号會發生:

1、當一個http操作完成時會發出這個信号

requestFinished(int requestId, int error)

2、當從伺服器讀到資料時會發送這個信号

dataReadProgress(int byteRead, int totalByte)

3、當收到伺服器的應答時會發出這個信号

responseHeaderReceived(const QHttpResponseHeader&)

3、執行個體

點選(此處)折疊或打開

#include "httpWindow.h"

HttpWindow::HttpWindow()

{

    urlLineEdit = new QLineEdit("http://");

    urlLabel = new QLabel(tr("&URL:"));

    urlLabel->setBuddy(urlLineEdit);

    statusLabel = new QLabel(tr("please input http addr"));

    downloadButton = new QPushButton(tr("download"));

    downloadButton->setDefault(true);

    progressDialog = new QProgressDialog(this);

    //建構QHttp類

    http = new QHttp(this);

    //綁定信号和槽函數

    connect(urlLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(enableDownload()));

    connect(http, SIGNAL(requestFinished(int, bool)), this, SLOT(requestFinishedSlot(int, bool)));

    connect(http, SIGNAL(dataReadProgress(int, int)), this, SLOT(dataReadProgressSlot(int, int)));

    connect(http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader&)), this, SLOT(responseHeaderReceivedSlot(const QHttpResponseHeader&)));

    connect(progressDialog, SIGNAL(canceled()), this, SLOT(cancleDownload()));

    connect(downloadButton, SIGNAL(clicked()), this, SLOT(downloadFile()));

    QHBoxLayout *topLayout = new QHBoxLayout();

    topLayout->addWidget(urlLabel);

    topLayout->addWidget(urlLineEdit);

    topLayout->addWidget(downloadButton);

    QVBoxLayout *mainLayout = new QVBoxLayout();

    mainLayout->addLayout(topLayout);

    mainLayout->addWidget(statusLabel);

    setLayout(mainLayout);

    urlLineEdit->setFocus();

}

//如果輸入框沒有網址,那麼就不能下載下傳

void HttpWindow::enableDownload()

    downloadButton->setEnabled(!urlLineEdit->text().isEmpty());

//開始下載下傳檔案

void HttpWindow::downloadFile()

    //取得輸入框的内容

    QUrl url(urlLineEdit->text());

    QFileInfo fileinfo(url.path());

    QString fileName = fileinfo.fileName();

    if(fileName.isEmpty())

        fileName = "index.html";

    //如果檔案已經存在就提示使用者是否覆寫

    if(QFile::exists(fileName))

    {

        if(QMessageBox::question(this, tr("HTTP"), tr("%1 is in,are you sure instead?").arg(fileName), QMessageBox::Yes, QMessageBox::No)==QMessageBox::No)

            return;

        QFile::remove(fileName);    

    }

    file = new QFile(fileName);

    if(!file->open(QIODevice::WriteOnly))

        QMessageBox::information(this, tr("12"),tr("23"));

        delete file;

        file = 0;

        return;

    //選擇連結類型https還是http

    QHttp::ConnectionMode mode = url.scheme().toLower()=="https" ? QHttp::ConnectionModeHttps:QHttp::ConnectionModeHttp;

    http->setHost(url.host(), mode, url.port()==-1?0:url.port());

    //設定使用者名和密碼

    if(url.userName().isEmpty())

        http->setUser(url.userName(), url.password());

    httpRequestAborted = false;

    QByteArray path = QUrl::toPercentEncoding(url.path(),"!$&'()*+,;=:@/");

    if(path.isEmpty())

        path = "/";

    //擷取檔案

    httpGetId = http->get(path, file);

    progressDialog->setWindowTitle("http");

    progressDialog->setLabelText("123");

    downloadButton->setEnabled(false);

//分析http伺服器的應答碼

void HttpWindow::responseHeaderReceivedSlot(const QHttpResponseHeader &responseHeader)

    switch(responseHeader.statusCode())

        case 200:

        case 301:

        case 302:

        case 303:

        case 307:

            break;

        default:

            QMessageBox::information(this, tr("failed"), tr("hehe"));

            httpRequestAborted = true;

            progressDialog->hide();

            http->abort();

//如果請求碼不是要擷取檔案,那麼就删除檔案

void HttpWindow::requestFinishedSlot(int requestId, bool error)

    if(requestId!=httpGetId)

    if(httpRequestAborted)

        if(file)

        {

            file->close();

            file->remove();

            delete file;

            file = 0;

        }

        progressDialog->hide();

    progressDialog->hide();

    file->close();

    if(error)

        file->remove();

        QMessageBox::information(this, tr("HTTP"), tr("down failed:%1").arg(http->errorString()));

    else

        QString fileName = QFileInfo(QUrl(urlLineEdit->text()).path()).fileName();

        statusLabel->setText(tr("down file here"));

    downloadButton->setEnabled(true);

    delete file;

    file = 0;

//更新進度條

void HttpWindow::dataReadProgressSlot(int byteRead, int totalByte)

    progressDialog->setMaximum(totalByte);

    progressDialog->setValue(byteRead);

//取消下載下傳

void HttpWindow::cancleDownload()

    statusLabel->setText("cancle");

    httpRequestAborted = true;

    http->abort();

二、socket

在LINUX下進行網絡程式設計,我們可以使用LINUX提供的統一的套接字接口。但是這種方法牽涉到太多的結構體,比如IP位址,端口轉換等,不熟練的人往往容易犯這樣那樣的錯誤。QT中提供的SOCKET完全使用了類的封裝機制,使使用者不需要接觸底層的各種結構體操作

1、傳輸層協定

傳輸層協定主要有兩種TCP和UDP

Tcp:面向連接配接的、可靠的、基于位元組流的傳輸層控制協定。TCP可以為應用程式提供可靠的資料傳輸,從一端發出的資料可以毫無差錯的傳送到另一端。在傳輸資料之前雙方必須建立連接配接,對于資料要求高的程式,可以使用TCP傳輸

Udp:提供無連接配接的不可靠的封包傳輸,一般可以用在以下場合:

1)、聊天軟體

2)、流媒體資料

3)、視訊聊天

2、TCP伺服器

TC伺服器建立的一般步驟:初始化、綁定、監聽、接受連接配接、傳輸資料、關閉

1)、Qt提供了QTcpServer類,可以幫組我們建立伺服器,這個類繼承自    QOBJECT

  QTcpServer server = new QTcpServer(this);

2)、使用listen方法來監聽

  server->listen(ip,port)

3)、nextPendingConnection建立連接配接,傳回QTcpSocket

QTcpSocket socket = server->nextPendingConnection()

4)、寫入資料write

socket->write();

#include "server.h"

Server::Server()

    //建立伺服器

    tcpServer = new QTcpServer();

    //開始監聽

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

        tcpServer->close();

    ipLabel = new QLabel(tr("伺服器IP"));

    portLabel = new QLabel(tr("端口"));

    ipLineEdit = new QLineEdit();

    portLineEdit = new QLineEdit();

    receiveLabel = new QLabel(tr("接收資料"));

    sendLabel = new QLabel(tr("發送資料"));

    sendTextEdit = new QTextEdit();

    receiveTextEdit = new QTextEdit();

    sendButton = new QPushButton(tr("發送"));

        ipLabel->setText((QString)tcpServer->serverAddress());

    QHBoxLayout *hLay1 = new QHBoxLayout();

    hLay1->addWidget(ipLabel);

    hLay1->addWidget(ipLineEdit);

    hLay1->addWidget(portLabel);

    hLay1->addWidget(portLineEdit);

    QHBoxLayout *hLay2 = new QHBoxLayout();

    hLay2->addWidget(sendLabel);

    hLay2->addWidget(receiveLabel);

    QHBoxLayout *hLay3 = new QHBoxLayout();

    hLay3->addWidget(sendTextEdit);

    hLay3->addWidget(receiveTextEdit);

    QVBoxLayout *mainLay = new QVBoxLayout();

    mainLay->addLayout(hLay1);

    mainLay->addLayout(hLay2);

    mainLay->addLayout(hLay3);

    mainLay->addWidget(sendButton);

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

    connect(sendButton, SIGNAL(clicked()), this, SLOT(sendMessage()));

    setLayout(mainLay);

    setWindowTitle(tr("TCP伺服器"));

    sendButton->setDisabled(true);

void Server::enableSend()

    //建立連結

    qDebug()"new connection!!!";

    sendButton->setEnabled(true);

    socket = tcpServer->nextPendingConnection();

void Server::sendMessage()

    //初始化資料

    QByteArray block;

    QDataStream out(&block, QIODevice::ReadWrite);

    out.device()->seek(0);

    outsendTextEdit->toPlainText();

    qDebug()"send";

    if(socket!=NULL)

        connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater()));

        socket->write(block);    

    if(socket==NULL)

        qDebug()"failed";

3、TCP用戶端

TCP用戶端建立的一般步驟:初始化套接字、建立連接配接、資料傳輸、關閉

1)、創造套接字

QTcpSocket socket = new QTcpSocket();

2)、連接配接到伺服器

socket->connectToHost(ip,port);

3)、傳輸資料

 當有資料來的時候會發出readyRead信号

#include "client.h"

Client::Client()

    QVBoxLayout *vLay = new QVBoxLayout();

    text = new QTextEdit();

    vLay->addWidget(text);

    setLayout(vLay);

    socket = new QTcpSocket();

    connect(socket, SIGNAL(readyRead()), SLOT(readMessage()));

    connect(socket, SIGNAL(disconnected()), SLOT(disSlot()));

    socket->connectToHost("LocalHost", 6789);

void Client::readMessage()

    QDataStream in(socket);

    QString m;

    in>>m;

    qDebug()m;

void Client::disSlot()

    qDebug()"disconnect";

    QString m

上一篇: SVN 解決沖突
下一篇: SVN 送出操作

繼續閱讀