lesson13-网络编程

简介: 一、QHttp 1、QT的应用层协议 QT为网络操作提供了自己封装的类,例如QFtp和QHttp就提供了应用层的文件传输 QHttp类用于构建http客户端程序,它提供了很多操作,例如最常用的get和post函数。
一、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、实例

点击(此处)折叠或打开

  1. #include "httpWindow.h"

  2. HttpWindow::HttpWindow()
  3. {
  4.     urlLineEdit = new QLineEdit("http://");
  5.     urlLabel = new QLabel(tr("&URL:"));
  6.     urlLabel->setBuddy(urlLineEdit);
  7.     statusLabel = new QLabel(tr("please input http addr"));
  8.     downloadButton = new QPushButton(tr("download"));
  9.     downloadButton->setDefault(true);
  10.     progressDialog = new QProgressDialog(this);
  11.     //构建QHttp类
  12.     http = new QHttp(this);
  13.     //绑定信号和槽函数
  14.     connect(urlLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(enableDownload()));
  15.     connect(http, SIGNAL(requestFinished(int, bool)), this, SLOT(requestFinishedSlot(int, bool)));
  16.     connect(http, SIGNAL(dataReadProgress(int, int)), this, SLOT(dataReadProgressSlot(int, int)));
  17.     connect(http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader&)), this, SLOT(responseHeaderReceivedSlot(const QHttpResponseHeader&)));
  18.     connect(progressDialog, SIGNAL(canceled()), this, SLOT(cancleDownload()));
  19.     connect(downloadButton, SIGNAL(clicked()), this, SLOT(downloadFile()));

  20.     QHBoxLayout *topLayout = new QHBoxLayout();
  21.     topLayout->addWidget(urlLabel);
  22.     topLayout->addWidget(urlLineEdit);
  23.     topLayout->addWidget(downloadButton);

  24.     QVBoxLayout *mainLayout = new QVBoxLayout();
  25.     mainLayout->addLayout(topLayout);
  26.     mainLayout->addWidget(statusLabel);
  27.     setLayout(mainLayout);
  28.     urlLineEdit->setFocus();
  29. }
  30. //如果输入框没有网址,那么就不能下载
  31. void HttpWindow::enableDownload()
  32. {
  33.     downloadButton->setEnabled(!urlLineEdit->text().isEmpty());
  34. }
  35. //开始下载文件
  36. void HttpWindow::downloadFile()
  37. {
  38.     //取得输入框的内容
  39.     QUrl url(urlLineEdit->text());
  40.     QFileInfo fileinfo(url.path());
  41.     QString fileName = fileinfo.fileName();
  42.     if(fileName.isEmpty())
  43.         fileName = "index.html";
  44.     //如果文件已经存在就提示用户是否覆盖
  45.     if(QFile::exists(fileName))
  46.     {
  47.         if(QMessageBox::question(this, tr("HTTP"), tr("%1 is in,are you sure instead?").arg(fileName), QMessageBox::Yes, QMessageBox::No)==QMessageBox::No)
  48.             return;
  49.         QFile::remove(fileName);    
  50.     }

  51.     file = new QFile(fileName);
  52.     if(!file->open(QIODevice::WriteOnly))
  53.     {
  54.         QMessageBox::information(this, tr("12"),tr("23"));
  55.         delete file;
  56.         file = 0;
  57.         return;
  58.     }
  59.     //选择链接类型https还是http
  60.     QHttp::ConnectionMode mode = url.scheme().toLower()=="https" ? QHttp::ConnectionModeHttps:QHttp::ConnectionModeHttp;
  61.     http->setHost(url.host(), mode, url.port()==-1?0:url.port());
  62.     //设置用户名和密码
  63.     if(url.userName().isEmpty())
  64.         http->setUser(url.userName(), url.password());
  65.     httpRequestAborted = false;
  66.     QByteArray path = QUrl::toPercentEncoding(url.path(),"!$&'()*+,;=:@/");
  67.     if(path.isEmpty())
  68.         path = "/";
  69.     //获取文件
  70.     httpGetId = http->get(path, file);

  71.     progressDialog->setWindowTitle("http");
  72.     progressDialog->setLabelText("123");
  73.     downloadButton->setEnabled(false);
  74. }
  75. //分析http服务器的应答码
  76. void HttpWindow::responseHeaderReceivedSlot(const QHttpResponseHeader &responseHeader)
  77. {
  78.     switch(responseHeader.statusCode())
  79.     {
  80.         case 200:
  81.         case 301:
  82.         case 302:
  83.         case 303:
  84.         case 307:
  85.             break;
  86.         default:
  87.             QMessageBox::information(this, tr("failed"), tr("hehe"));
  88.             httpRequestAborted = true;
  89.             progressDialog->hide();
  90.             http->abort();
  91.     }
  92. }
  93. //如果请求码不是要获取文件,那么就删除文件
  94. void HttpWindow::requestFinishedSlot(int requestId, bool error)
  95. {
  96.     if(requestId!=httpGetId)
  97.         return;
  98.     if(httpRequestAborted)
  99.     {
  100.         if(file)
  101.         {
  102.             file->close();
  103.             file->remove();
  104.             delete file;
  105.             file = 0;
  106.         }
  107.         progressDialog->hide();
  108.         return;
  109.     }
  110.     progressDialog->hide();
  111.     file->close();
  112.     if(error)
  113.     {
  114.         file->remove();
  115.         QMessageBox::information(this, tr("HTTP"), tr("down failed:%1").arg(http->errorString()));
  116.     }
  117.     else
  118.     {
  119.         QString fileName = QFileInfo(QUrl(urlLineEdit->text()).path()).fileName();
  120.         statusLabel->setText(tr("down file here"));
  121.     }
  122.     downloadButton->setEnabled(true);
  123.     delete file;
  124.     file = 0;
  125. }
  126. //更新进度条
  127. void HttpWindow::dataReadProgressSlot(int byteRead, int totalByte)
  128. {
  129.     if(httpRequestAborted)
  130.         return;
  131.     progressDialog->setMaximum(totalByte);
  132.     progressDialog->setValue(byteRead);
  133. }
  134. //取消下载
  135. void HttpWindow::cancleDownload()
  136. {
  137.     statusLabel->setText("cancle");
  138.     httpRequestAborted = true;
  139.     http->abort();
  140.     downloadButton->setEnabled(true);
  141. }



二、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();

点击(此处)折叠或打开

  1. #include "server.h"

  2. Server::Server()
  3. {
  4.     //创建服务器
  5.     tcpServer = new QTcpServer();
  6.     //开始监听
  7.     if(!tcpServer->listen(QHostAddress::Any, 6789))
  8.     {
  9.         tcpServer->close();
  10.         return;
  11.     }
  12.     ipLabel = new QLabel(tr("服务器IP"));
  13.     portLabel = new QLabel(tr("端口"));
  14.     ipLineEdit = new QLineEdit();
  15.     portLineEdit = new QLineEdit();
  16.     receiveLabel = new QLabel(tr("接收数据"));
  17.     sendLabel = new QLabel(tr("发送数据"));
  18.     sendTextEdit = new QTextEdit();
  19.     receiveTextEdit = new QTextEdit();
  20.     sendButton = new QPushButton(tr("发送"));
  21.         ipLabel->setText((QString)tcpServer->serverAddress());
  22.     QHBoxLayout *hLay1 = new QHBoxLayout();
  23.     hLay1->addWidget(ipLabel);
  24.     hLay1->addWidget(ipLineEdit);
  25.     hLay1->addWidget(portLabel);
  26.     hLay1->addWidget(portLineEdit);
  27.     QHBoxLayout *hLay2 = new QHBoxLayout();
  28.     hLay2->addWidget(sendLabel);
  29.     hLay2->addWidget(receiveLabel);
  30.     QHBoxLayout *hLay3 = new QHBoxLayout();
  31.     hLay3->addWidget(sendTextEdit);
  32.     hLay3->addWidget(receiveTextEdit);
  33.     QVBoxLayout *mainLay = new QVBoxLayout();
  34.     mainLay->addLayout(hLay1);
  35.     mainLay->addLayout(hLay2);
  36.     mainLay->addLayout(hLay3);
  37.     mainLay->addWidget(sendButton);
  38.     
  39.     connect(tcpServer, SIGNAL(newConnection()), this, SLOT(enableSend()));
  40.     connect(sendButton, SIGNAL(clicked()), this, SLOT(sendMessage()));
  41.     setLayout(mainLay);
  42.     setWindowTitle(tr("TCP服务器"));
  43.     sendButton->setDisabled(true);

  44. }

  45. void Server::enableSend()
  46. {
  47.     //建立链接
  48.     qDebug()"new connection!!!";
  49.     sendButton->setEnabled(true);
  50.     socket = tcpServer->nextPendingConnection();
  51. }
  52. void Server::sendMessage()
  53. {
  54.     //初始化数据
  55.     QByteArray block;
  56.     QDataStream out(&block, QIODevice::ReadWrite);
  57.     out.device()->seek(0);
  58.     outsendTextEdit->toPlainText();

  59.     qDebug()"send";
  60.     if(socket!=NULL)
  61.     {
  62.         connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater()));
  63.         socket->write(block);    
  64.     }
  65.     if(socket==NULL)
  66.         qDebug()"failed";
  67. }


3、TCP客户端
TCP客户端建立的一般步骤:初始化套接字、建立连接、数据传输、关闭

1)、创造套接字
QTcpSocket socket = new QTcpSocket();
2)、连接到服务器
socket->connectToHost(ip,port);
3)、传输数据
 当有数据来的时候会发出readyRead信号


点击(此处)折叠或打开

  1. #include "client.h"

  2. Client::Client()
  3. {
  4.     QVBoxLayout *vLay = new QVBoxLayout();
  5.     text = new QTextEdit();
  6.     vLay->addWidget(text);
  7.     setLayout(vLay);
  8.     socket = new QTcpSocket();
  9.     connect(socket, SIGNAL(readyRead()), SLOT(readMessage()));
  10.     connect(socket, SIGNAL(disconnected()), SLOT(disSlot()));
  11.     socket->connectToHost("LocalHost", 6789);
  12. }

  13. void Client::readMessage()
  14. {
  15.     QDataStream in(socket);
  16.     QString m;
  17.     in>>m;
  18.     qDebug()m;
  19. }
  20. void Client::disSlot()
  21. {
  22.     qDebug()"disconnect";
  23. }


点击(此处)折叠或打开

  1. #include "client.h"

  2. Client::Client()
  3. {
  4.     QVBoxLayout *vLay = new QVBoxLayout();
  5.     text = new QTextEdit();
  6.     vLay->addWidget(text);
  7.     setLayout(vLay);
  8.     socket = new QTcpSocket();
  9.     connect(socket, SIGNAL(readyRead()), SLOT(readMessage()));
  10.     connect(socket, SIGNAL(disconnected()), SLOT(disSlot()));
  11.     socket->connectToHost("LocalHost", 6789);
  12. }

  13. void Client::readMessage()
  14. {
  15.     QDataStream in(socket);
  16.     QString m
相关文章
|
7月前
|
网络协议 Java
【JavaSE】网络编程
【JavaSE】网络编程
56 0
|
存储 安全 编译器
lesson0-C++入门 3
lesson0-C++入门
53 0
|
编译器 C语言 C++
lesson0-C++入门 2
lesson0-C++入门
68 0
|
编译器 C语言 C++
lesson0-C++入门 1
lesson0-C++入门
56 0
|
3月前
|
域名解析 网络协议 应用服务中间件
网络编程入门如此简单(四):一文搞懂localhost和127.0.0.1
本文将以网络编程入门者视角,言简意赅地为你请清楚localhost和127.0.0.1的关系及区别等。
158 2
网络编程入门如此简单(四):一文搞懂localhost和127.0.0.1
|
7月前
|
编译器 测试技术
lesson3-C++类和对象(下)(三)
lesson3-C++类和对象(下)(三)
49 0
|
7月前
|
存储 编译器 C语言
lesson1-C++类和对象(上)
lesson1-C++类和对象(上)
61 0
|
7月前
|
Java C++
lesson3-C++类和对象(下)(二)
lesson3-C++类和对象(下)(二)
50 0
|
开发框架
J2EE练习_chapter14网络编程
J2EE练习_chapter14网络编程
|
存储 安全 Java