一、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