您的位置:首页 > 编程语言 > Qt开发

Qt网络编程

2015-05-31 23:00 429 查看
Qt网络编程
sf2gis@163.com
2015年5月2日

1 目标:在网络上不同的计算机之间进行交互。

原理:构造不同的传输协议,在不同的主机之间进行按照协议标准进行请求和回复。

方法:HTTP,FTP,TCP,UDP

使用QtNetwork框架的相关类操作。

1.1 Qt 操作

协议管理:使用QUrl进行Url构造,包含对协议、用户名、密码等设置。

请求:QNetworkRequest。

回复:QNetworkReply。

操作管理:QNetworkAccessManager。负责进行HTTP操作及状态。

进度:QNetworkReply发送downloadProgress()信号。

1.2 示例

1.2.1 Http请求页面

voidMainWindow::http()

{

QNetworkAccessManager *pManager = newQNetworkAccessManager(this);

connect(pManager,SIGNAL(finished(QNetworkReply*)),this,SLOT(handleReply(QNetworkReply*)));

QNetworkReply *reply =pManager->get(QNetworkRequest(QUrl("http://www.gfsoso.net/")));

connect(reply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(handleProgress(qint64,qint64)));

}



voidMainWindow::handleReply(QNetworkReply *reply)

{

QString strReply(reply->readAll());

qDebug()<<strReply;

ui->textBrowser->setText(strReply);

reply->deleteLater();

}



voidMainWindow::handleProgress(qint64 readBytes,qint64 totalBytes)

{

ui->progressBar->setMaximum(totalBytes);

ui->progressBar->setValue(readBytes);

}

1.2.2 FTP下载文件

voidMainWindow::handleReply(QNetworkReply *reply)

{

QByteArray ba = reply->readAll();

QString strReply(ba);

qDebug()<<strReply;

ui->textBrowser->setText(strReply);

QFile file("test.tar.gz");

file.open(QFile::WriteOnly);

file.write(ba);

file.close();

reply->deleteLater();

}



voidMainWindow::handleProgress(qint64 readBytes,qint64 totalBytes)

{

ui->progressBar->setMaximum(totalBytes);

ui->progressBar->setValue(readBytes);

}



voidMainWindow::ftp()

{

QNetworkAccessManager *pManager = newQNetworkAccessManager(this);

connect(pManager,SIGNAL(finished(QNetworkReply*)),this,SLOT(handleReply(QNetworkReply*)));

QNetworkReply *reply =pManager->get(QNetworkRequest(QUrl("ftp://ftp.pku.edu.cn/open/db/MySQL/mysql-connector-java-5.1.21.tar.gz")));

connect(reply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(handleProgress(qint64,qint64)));

}



2 Http :HypeText Tranfer Protoco,超文本传输协议

2.1 目标:发送和接收HTML。

2.2 方法:

提供多种操作方式,如get(请求URL),Post(请求处理数据),PUT(上传数据),DELETE(删除),CONNECT(连接到TCP/IP),OPTIONS(返回所有支持的方法),HEAD(仅返回头)。其中CURD对应POST,PUT,GET,DELETE。

GET与POST的区别:get使用url的一部分传递参数,可见,长度有限(2048),只能传递ascii。post使用单独传递数据,不可见,长度不了,可传递二进制数据。

参考:http://www.w3school.com.cn/tags/html_ref_httpmethods.asp

http://zh.wikipedia.org/zh/%E8%B6%85%E6%96%87%E6%9C%AC%E4%BC%A0%E8%BE%93%E5%8D%8F%E8%AE%AE

REST和SOAP:目标简单的进行web service。REST使用HTTP方式CRUD,无状态,简单,安全性差,将所有对象抽象为资源,以URL进行请求。SOAP只使用POST,有状态,使用复杂,安全性好,将所有数据封装为XML进行交互。

参考:http://www.cnblogs.com/zhangz721/archive/2009/10/02/1577316.html

示例:参见Http请求页面

3 FTP :File Tranfer Protoco,文件传输协议

目标:文件在网络中的传输。

方法:使用20端口传输文件,21端口传输命令。

参考:

http://zh.wikipedia.org/zh/%E6%96%87%E4%BB%B6%E4%BC%A0%E8%BE%93%E5%8D%8F%E8%AE%AE

3.1 Qt操作

Qt4使用QFtp,但是有消息丢失现象。Qt5之后建议使用QNetworkAccessManager。

示例:参见FTP下载文件

参考:

http://blog.csdn.net/fuyoufang1/article/details/18215081

4 主机信息

目标:区分网络中不同的主机。

原理:IP:internet protocol,互联网协议,为不同的主机分配唯一的ip地址。DNS(Domain NameService)将不同Url中名称解析为ip地址。IP地址有IPV4和IPV6两种。

子网掩码:区分不同局域网网段的掩码,过滤相同部分,以确定所属的网段。

网关:外部网络出口。局域网网络向外部发送数据时,会发送到网关,再由网关转发到目的网络。

参考:http://www.hackbase.com/tech/2015-01-12/70390.html

http://zh.wikipedia.org/wiki/%E7%BD%91%E5%85%B3

4.1 方法:QHostInfo。

获取域名的IP地址:QHostInfo::fromName(),同步获取;QHostInfo::lookupHost(“域名”),异步获取。

获取IP地址的域名:QHostInfo::lookupHost(“IP地址”)。

示例:

void MainWindow::hostInfo()

{

qDebug()<<QHostInfo::localDomainName()<<","<<QHostInfo::localHostName();

qDebug()<<QHostInfo::fromName("www.baidu.com").addresses();

QHostInfo::lookupHost("www.baidu.com",this,SLOT(handleHost(QHostInfo)));

}



voidMainWindow::handleHost(const QHostInfo &hostInfo)

{

foreach(const QHostAddress&addr,hostInfo.addresses())

{

qDebug()<<addr.toString();

}

}

4.2 方法:QNetworkInterface,QNetworkAddressEntry。

网卡信息:QNetworkInterface,当前主机上所有网卡(包括虚拟)的信息。

IP信息:QNetworkAddressEntry,每一个IP地址及其子网掩码和网关信息。

参考:http://blog.klniu.com/post/qnetworkinterface-class/

示例:

void MainWindow::interfaces()

{

qDebug()<<QNetworkInterface::allAddresses();

foreach(const QNetworkInterface&interface,QNetworkInterface::allInterfaces())

{

qDebug()<<"interface:"<<interface.name()<<interface.hardwareAddress();

foreach(const QNetworkAddressEntry&entry,interface.addressEntries())

{

qDebug()<<"Entry:"<<entry.ip()<<entry.netmask()<<entry.broadcast();

}

}

}

结果

(QHostAddress("fe80::2507:109f:3858:d133%15"), QHostAddress( "169.254.209.51" ) , QHostAddress( "192.168.22.1") , QHostAddress( "fe80::4cc6:bb45:659f:58a9%12" ) , QHostAddress("169.254.88.169" ) , QHostAddress( "192.168.1.102" ) ,QHostAddress( "fe80::254b:6d06:925:b6f5%20"
) , QHostAddress("192.168.206.1" ) , QHostAddress("fe80::8c8a:179b:ecb0:a9d3%22" ) , QHostAddress("192.168.217.1" ) , QHostAddress( "::1" ) , QHostAddress("127.0.0.1" ) , QHostAddress( "fe80::5efe:c0a8:d901%18" ) ,QHostAddress( "2001:0:9d38:6ab8:188f:ad3d:8a8d:71e3"
) , QHostAddress("fe80::188f:ad3d:8a8d:71e3%17" ) , QHostAddress( "fe80::5efe:c0a8:166%23") )

interface:"{6059E8E0-FCF5-4B12-9C6D-EC97B540E1AD}""44:6D:57:5E:95:73"

Entry: QHostAddress("fe80::2507:109f:3858:d133%15" ) QHostAddress("ffff:ffff:ffff:ffff::" ) QHostAddress( "" )

Entry: QHostAddress("169.254.209.51" ) QHostAddress( "" ) QHostAddress("" )

Entry: QHostAddress("192.168.22.1" ) QHostAddress( "" ) QHostAddress("" )

interface:"{253576A5-E502-4A9C-9394-88D45EE4B107}""00:21:CC:C8:A1:CF"

Entry: QHostAddress("fe80::4cc6:bb45:659f:58a9%12" ) QHostAddress( "ffff:ffff:ffff:ffff::") QHostAddress( "" )

Entry: QHostAddress("169.254.88.169" ) QHostAddress( "" ) QHostAddress("" )

interface:"{33AC696B-F917-423B-A17B-88AFFA264C4C}""44:6D:57:5E:95:73"

Entry: QHostAddress("192.168.1.102" ) QHostAddress( "255.255.255.0" )QHostAddress( "192.168.1.255" )

interface:"{A1696BDD-A453-4D81-9AFC-A22A7553EAAD}""00:50:56:C0:00:01"

Entry: QHostAddress("fe80::254b:6d06:925:b6f5%20" ) QHostAddress("ffff:ffff:ffff:ffff::" ) QHostAddress( "" )

Entry: QHostAddress("192.168.206.1" ) QHostAddress( "255.255.255.0" )QHostAddress( "192.168.206.255" )

interface:"{5F04202D-B1C9-4CD3-951F-F1FD4C091D2E}""00:50:56:C0:00:08"

Entry: QHostAddress("fe80::8c8a:179b:ecb0:a9d3%22" ) QHostAddress("ffff:ffff:ffff:ffff::" ) QHostAddress( "" )

Entry: QHostAddress("192.168.217.1" ) QHostAddress( "255.255.255.0" )QHostAddress( "192.168.217.255" )

interface:"{846EE342-7039-11DE-9D20-806E6F6E6963}" ""

Entry: QHostAddress("::1" ) QHostAddress("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" ) QHostAddress("" )

Entry: QHostAddress("127.0.0.1" ) QHostAddress( "" ) QHostAddress( "")

interface:"{E021EE1B-15F5-425A-92CE-685790FE0031}" "00:00:00:00:00:00:00:E0"

interface:"{31FDE048-BFF0-4DB6-9D80-4362D1CAE28F}""00:00:00:00:00:00:00:E0"

Entry: QHostAddress("fe80::5efe:c0a8:d901%18" ) QHostAddress("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" ) QHostAddress("" )

interface:"{C534E5AC-9EA2-4E25-8017-8F5628B7338D}""00:00:00:00:00:00:00:E0"

Entry: QHostAddress("2001:0:9d38:6ab8:188f:ad3d:8a8d:71e3" ) QHostAddress( "::") QHostAddress( "" )

Entry: QHostAddress("fe80::188f:ad3d:8a8d:71e3%17" ) QHostAddress("ffff:ffff::" ) QHostAddress( "" )

interface: "{E858920C-9CEA-4C35-9F85-9609D71CA21D}""00:00:00:00:00:00:00:E0"

interface:"{3B61355E-6D8F-441F-9379-020F9551733B}""00:00:00:00:00:00:00:E0"

interface:"{7E8F026C-AA3B-4F39-AA8E-5726B3382763}""00:00:00:00:00:00:00:E0"

interface:"{3D3A432C-5A7E-4E00-BA86-EE4309C419EF}""00:00:00:00:00:00:00:E0"

Entry: QHostAddress("fe80::5efe:c0a8:166%23" ) QHostAddress("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" ) QHostAddress("" )

5 UDP:用户数据报协议,User Datagram Protocol

目标:简单快速的传输数据。

原理:发送方设置数据及其相关信息(发送方地址:端口,目标地址:端口,长度,校验,数据等)打包发送,不再处理其它问题。

端口:目标是区分指同一协议下的不同连接。0~65535,1024之下系统保留,应尽量使用大的端口号。

参考:http://www.nwnu.edu.cn/Article.do_id=301.html

方法:UDP,短小快速,数据量应该尽量少,一般不要超过512B。

监听指定IP:Port:bind()。只有服务端需要绑定端口以固定收发地址,客户端动态绑定。

发送数据:writeDatagram直接发送,动态绑定端口。

接收数据:事件驱动,发送readyRead()消息。hasPendingDatagram()检测是否有数据,readDatagram()读取数据。

示例:

发送方:ip=192.168.1.102

void MainWindow::udpSender()

{

QUdpSocket *pSender = new QUdpSocket(this);

QByteArray ba("againxx");

pSender->writeDatagram(ba,QHostAddress("192.168.217.129"),12306);

}

接收方:ip=192.168.217.129

void MainWindow::receive()

{

QUdpSocket *pUdp = new QUdpSocket(this);

pUdp->bind(12306,QAbstractSocket::ShareAddress);

connect(pUdp,SIGNAL(readyRead()),this,SLOT(handleUdpData()));

m_pUdp = pUdp;

}

voidMainWindow::handleUdpData()

{

while(m_pUdp->hasPendingDatagrams())

{

int iSize=m_pUdp->pendingDatagramSize();

QByteArray baDatagram;

baDatagram.resize(iSize);

QHostAddress host;

quint16 port;

m_pUdp->readDatagram(baDatagram.data(),iSize,&host,&port);

qDebug()<<"receive-"<<host.toString()<<":"<<port<<"="<<baDatagram;

}

}



6 TCP:传输控制协议,Transformation Control Protocol

目标:稳定的连接传输。可重复发送、校验数据。

原理:底层协议,HTTP,FTP等都是基于TCP协议。

方法:QTcpSocket

连接双方:QTcpSocket作为连接实例。一次连接使用一个socket。使用connectToHost()连接到服务器。

服务器监听:使用QTcpServer,用于监听指定接口。连接使用事件驱动,有新连接时发送newConnection()信号。

发送:write()

接收:bytesAvread(),QIODevice类的读写方式。

示例:

客户端:

void MainWindow::tcpClient()

{

QTcpSocket *pClient = new QTcpSocket(this);

connect(pClient,SIGNAL(connected()),this,SLOT(handleConnect()));

connect(pClient,SIGNAL(readyRead()),this,SLOT(handleRead ()));

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

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

pClient->abort();

pClient->connectToHost(QHostAddress::LocalHost,12306);

}

voidMainWindow::displayError(QAbstractSocket::SocketError error){

qDebug()<<"error"<<error;

}

void MainWindow::handleRead()

{

QTcpSocket *pClient = (QTcpSocket *)sender();

if(pClient->bytesAvailable()){

qDebug()<<"server:"<<pClient->readAll();

}

}

voidMainWindow::handleConnect()

{

QTcpSocket *pClient = (QTcpSocket *)sender();

pClient->write("abcd-tcp");

if(pClient->bytesAvailable()){

qDebug()<<pClient->read(100);

}

}

服务端:

void MainWindow::receiveTcp()

{

QTcpServer *pTcp = new QTcpServer(this);

if(!pTcp->listen(QHostAddress::LocalHost,12306)){

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

}

qDebug()<<"listening..."<<pTcp->isListening()<<pTcp->serverAddress();

connect(pTcp,SIGNAL(newConnection()),this,SLOT(handleTcp()));

}



void MainWindow::handleTcp()

{

QTcpServer *pTcp = (QTcpServer *)sender();

QTcpSocket *pSocket =pTcp->nextPendingConnection();

if(pSocket)

{

connect(pSocket,SIGNAL(readyRead()),this,SLOT(handleClientData()));

qDebug()<<pSocket->peerAddress()<<pSocket->peerPort()<<pSocket->peerName();

}

}



void MainWindow::handleClientData()

{

QTcpSocket *pSocket = (QTcpSocket*)sender();

if(pSocket->bytesAvailable())

{

qDebug()<<pSocket->peerAddress()<<pSocket->peerPort()<<pSocket->peerName();

qDebug()<<pSocket->readAll();

pSocket->write("xxx-ubuntu");

}

}



7 浏览器:WebKit

目标:创建能够浏览网页的浏览器,可能解析HTML、CSS、JavaScript等。

原理:基于开源项目(WebKit)开发的浏览器。

方法:QtWebKit。

浏览器对象:QWebView(控件)。

页面对象:QWebPage。

DOM:QWebFrame,QWebElement。

历史记录:QWebHistoryItem。

示例:

ui->webView->load(QUrl("http://www.baidu.com/"));
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: