0


QT/C++——网络编程

一、基础知识复习

这部分内容前面讲的比较详细,现在就是简单复习一下。

两台主机之间通信要经过封包他有一堆包头

TCP、UDP都是基于套接字,C写我感觉已经挺简单了,老师说C++更简单,我们往下学学看。

二、UDP

网络编程这块要在工程文件中加上network

服务器是被动套接字,客户端是主动套接字

客户端:

  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3. #include <QWidget>
  4. #include <QTextEdit>
  5. #include <QLineEdit>
  6. #include <QPushButton>
  7. #include <QUdpSocket>
  8. #include <QHostAddress>
  9. class Widget : public QWidget
  10. {
  11. Q_OBJECT
  12. public slots:
  13. void senddata()
  14. {
  15. udpsock->writeDatagram(le->text().toStdString().c_str(), QHostAddress("192.168.3.27"), 8888);
  16. }
  17. void recvdata()
  18. {
  19. QByteArray datagram;
  20. datagram.resize(udpsock->pendingDatagramSize());
  21. QHostAddress sender;
  22. quint16 senderPort;
  23. udpsock->readDatagram(datagram.data(), datagram.size(),
  24. &sender, &senderPort);
  25. te->append(datagram);
  26. }
  27. public:
  28. Widget(QWidget *parent = 0);
  29. ~Widget();
  30. private:
  31. QTextEdit *te;
  32. QLineEdit *le;
  33. QPushButton *pb;
  34. QUdpSocket *udpsock;
  35. };
  36. #endif // WIDGET_H
  1. #include "widget.h"
  2. #include <QVBoxLayout>
  3. Widget::Widget(QWidget *parent)
  4. : QWidget(parent)
  5. {
  6. te = new QTextEdit;
  7. le = new QLineEdit;
  8. pb = new QPushButton("send");
  9. QVBoxLayout *vbox = new QVBoxLayout;
  10. vbox->addWidget(te);
  11. vbox->addWidget(le);
  12. vbox->addWidget(pb);
  13. setLayout(vbox);
  14. udpsock = new QUdpSocket;
  15. connect(pb, SIGNAL(clicked(bool)), this, SLOT(senddata()));
  16. connect(udpsock, SIGNAL(readyRead()), this, SLOT(recvdata()));
  17. }
  18. Widget::~Widget()
  19. {
  20. }

服务器:

  1. #ifndef UDPSERVER_H
  2. #define UDPSERVER_H
  3. #include <QObject>
  4. #include <QUdpSocket>
  5. #include <QDebug>
  6. class udpServer : public QObject
  7. {
  8. Q_OBJECT
  9. public:
  10. explicit udpServer(QObject *parent = 0);
  11. void init()
  12. {
  13. udpSocket = new QUdpSocket(this);
  14. udpSocket->bind(QHostAddress::AnyIPv4, 8888);
  15. connect(udpSocket, SIGNAL(readyRead()),
  16. this, SLOT(readPendingDatagrams()));
  17. qDebug()<<"init....";
  18. }
  19. signals:
  20. public slots:
  21. void readPendingDatagrams()
  22. {
  23. while (udpSocket->hasPendingDatagrams()) {
  24. QByteArray datagram;
  25. datagram.resize(udpSocket->pendingDatagramSize());
  26. QHostAddress sender;
  27. quint16 senderPort;
  28. udpSocket->readDatagram(datagram.data(), datagram.size(),
  29. &sender, &senderPort);
  30. //processTheDatagram(datagram);
  31. qDebug()<<"recv: "<<datagram;
  32. udpSocket->writeDatagram(datagram.data(), datagram.size(),
  33. sender, senderPort);
  34. }
  35. }
  36. private:
  37. QUdpSocket *udpSocket;
  38. };
  39. #endif // UDPSERVER_H

两个程序的工程文件中一定要加入network

三、TCP

服务器:

  1. #ifndef TCPSERVER_H
  2. #define TCPSERVER_H
  3. #include <QObject>
  4. #include <QTcpServer>
  5. #include <QTcpSocket>
  6. #include <QDebug>
  7. class tcpServer : public QObject
  8. {
  9. Q_OBJECT
  10. public:
  11. explicit tcpServer(QObject *parent = 0);
  12. signals:
  13. public slots:
  14. void newconnected()
  15. {
  16. qDebug()<<"connected";
  17. clientsock = ser->nextPendingConnection();
  18. connect(clientsock, SIGNAL(readyRead()), this, SLOT(readdata()));
  19. }
  20. void readdata()
  21. {
  22. QByteArray buf = clientsock->readAll();
  23. qDebug()<<"recv: "<<buf;
  24. clientsock->write(buf);
  25. }
  26. private:
  27. QTcpServer *ser;
  28. QTcpSocket *clientsock;
  29. };
  30. #endif // TCPSERVER_H
  1. #include "tcpserver.h"
  2. #include <QHostAddress>
  3. tcpServer::tcpServer(QObject *parent) : QObject(parent)
  4. {
  5. ser = new QTcpServer;
  6. ser->listen(QHostAddress::AnyIPv4, 8888);
  7. connect(ser, SIGNAL(newConnection()), this, SLOT(newconnected()));
  8. ser->waitForNewConnection();
  9. }

客户端:

  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3. #include <QWidget>
  4. #include <QTextEdit>
  5. #include <QLineEdit>
  6. #include <QPushButton>
  7. #include <QTcpSocket>
  8. class Widget : public QWidget
  9. {
  10. Q_OBJECT
  11. public slots:
  12. void senddata()
  13. {
  14. tcpsocket->write(le->text().toStdString().c_str());
  15. }
  16. void recvdata()
  17. {
  18. QByteArray buf = tcpsocket->readAll();
  19. te->append(buf);
  20. }
  21. public:
  22. Widget(QWidget *parent = 0);
  23. ~Widget();
  24. private:
  25. QTextEdit *te;
  26. QLineEdit *le;
  27. QPushButton *pb;
  28. QTcpSocket *tcpsocket;
  29. };
  30. #endif // WIDGET_H
  1. #include "widget.h"
  2. #include <QVBoxLayout>
  3. #include <QHostAddress>
  4. Widget::Widget(QWidget *parent)
  5. : QWidget(parent)
  6. {
  7. te = new QTextEdit;
  8. le = new QLineEdit;
  9. pb = new QPushButton("send");
  10. QVBoxLayout *vbox = new QVBoxLayout;
  11. vbox->addWidget(te);
  12. vbox->addWidget(le);
  13. vbox->addWidget(pb);
  14. setLayout(vbox);
  15. tcpsocket = new QTcpSocket;
  16. //connect to server
  17. tcpsocket->connectToHost(QHostAddress("192.168.3.27"), 8888);
  18. connect(pb, SIGNAL(clicked(bool)), this, SLOT(senddata()));
  19. connect(tcpsocket, SIGNAL(readyRead()), this, SLOT(recvdata()));
  20. }
  21. Widget::~Widget()
  22. {
  23. }

四、小项目

实现一个类似于监控的东西

就是把传输内容换成了照片

客户端:

  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3. #include <QWidget>
  4. #include <QLabel>
  5. #include <QLineEdit>
  6. #include <QTcpSocket>
  7. #include <QPushButton>
  8. #include <QHostAddress>
  9. #include <QDebug>
  10. #include <QPixmap>
  11. class Widget : public QWidget
  12. {
  13. Q_OBJECT
  14. public:
  15. Widget(QWidget *parent = 0);
  16. ~Widget();
  17. public slots:
  18. void startv()
  19. {
  20. readsize = true;
  21. sockv = new QTcpSocket(this);
  22. connect(sockv, SIGNAL(readyRead()), this, SLOT(recv_show()));
  23. sockv->connectToHost(QHostAddress(leip->text()), atoi(leport->text().toStdString().c_str()));
  24. btstart->setText("STOP");
  25. leip->setDisabled(true);
  26. leport->setDisabled(true);
  27. disconnect(btstart, SIGNAL(clicked()), this, SLOT(startv()));
  28. connect(btstart, SIGNAL(clicked()), this, SLOT(stop()));
  29. }
  30. void stop()
  31. {
  32. sockv->close();
  33. sockv->deleteLater();
  34. disconnect(btstart, SIGNAL(clicked()), this, SLOT(stop()));
  35. connect(btstart, SIGNAL(clicked()), this, SLOT(startv()));
  36. leip->setDisabled(false);
  37. leport->setDisabled(false);
  38. btstart->setText("START");
  39. }
  40. void recv_show()
  41. {
  42. if(readsize){ //接收图片大小
  43. char buf[10] = {0};
  44. sockv->read(buf, 10);
  45. picsize = atoi(buf); //转成整形大小值
  46. // qDebug()<<picsize;
  47. readsize = false;
  48. }
  49. else
  50. {
  51. if(sockv->bytesAvailable() < picsize) //等待图片内容接收完整
  52. return;
  53. char buf[640*480*3];
  54. sockv->read(buf, picsize);
  55. QPixmap pix;
  56. pix.loadFromData((uchar*)buf, picsize, "jpeg");
  57. lbvideo->setPixmap(pix);//切换照片
  58. readsize = true;
  59. }
  60. }
  61. private:
  62. QLabel *lbvideo, *lbip, *lbport;
  63. QLineEdit *leip, *leport;
  64. QPushButton *btstart;
  65. QTcpSocket *sockv;
  66. bool readsize;
  67. int picsize;
  68. };
  69. #endif // WIDGET_H
  1. #include "widget.h"
  2. #include <QHBoxLayout>
  3. #include <QVBoxLayout>
  4. Widget::Widget(QWidget *parent)
  5. : QWidget(parent)
  6. {
  7. lbvideo = new QLabel;
  8. lbvideo->setFixedSize(640,480);
  9. lbvideo->setScaledContents(true);
  10. lbip = new QLabel("IP");
  11. lbport = new QLabel("PORT");
  12. leip = new QLineEdit("192.168.3.27");
  13. leport = new QLineEdit("8888");
  14. btstart = new QPushButton("START");
  15. QHBoxLayout *hbox = new QHBoxLayout;
  16. hbox->addWidget(lbip);
  17. hbox->addWidget(leip);
  18. hbox->addWidget(lbport);
  19. hbox->addWidget(leport);
  20. hbox->addWidget(btstart);
  21. QVBoxLayout *vbox = new QVBoxLayout;
  22. vbox->addLayout(hbox);
  23. vbox->addWidget(lbvideo);
  24. setLayout(vbox);
  25. connect(btstart, SIGNAL(clicked()), this, SLOT(startv()));
  26. }
  27. Widget::~Widget()
  28. {
  29. }

服务器:

  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3. #include <QWidget>
  4. #include <QCamera>
  5. #include <QCameraViewfinder>
  6. #include <QCameraImageCapture>
  7. #include <QLabel>
  8. #include <QTimerEvent>
  9. #include <QDebug>
  10. #include <QPixmap>
  11. #include <QTcpServer>
  12. #include <QTcpSocket>
  13. #include <QTemporaryFile>
  14. #include <QFile>
  15. #include <QBuffer>
  16. class Widget : public QWidget
  17. {
  18. Q_OBJECT
  19. public:
  20. Widget(QWidget *parent = 0);
  21. ~Widget();
  22. public slots:
  23. void show_pic(int i, QImage img)
  24. {
  25. QPixmap pix(1920, 1080);
  26. #if 1
  27. pix.fill(Qt::red);
  28. pix = pix.fromImage(img);
  29. lb_pic->setPixmap(pix);
  30. #else
  31. lb_pic->setPixmap(QPixmap::fromImage(img));
  32. #endif
  33. // qDebug()<<i;
  34. if(client&&client->isWritable())
  35. {
  36. // qDebug()<<"sending "<<pix.size();
  37. #if 0
  38. pix.save("tem.jpg","jpeg");
  39. // qDebug()<<"saveed";
  40. QFile tem("tem.jpg");
  41. tem.open(QIODevice::ReadOnly);
  42. #else
  43. QBuffer tem;
  44. pix.save(&tem, "jpeg");
  45. #endif
  46. char buf[10] = {0};
  47. // qDebug()<<"size: "<<buf;
  48. sprintf(buf, "%d", tem.size());
  49. // qDebug()<<"size: "<<buf;
  50. client->write(buf, 10);//发大小(大小值先转换成字符串装在固定的10个字节的buff中发送)
  51. // qDebug()<<"size ok";
  52. #if 0
  53. QByteArray data = tem.readAll();
  54. #else
  55. QByteArray data(tem.buffer());
  56. #endif
  57. client->write(data);//发图片内容
  58. // qDebug()<<"finish";
  59. tem.close();
  60. }
  61. }
  62. void accept_client()
  63. {
  64. if(NULL != client)
  65. {
  66. client->close();
  67. client->deleteLater();
  68. }
  69. client = myserver->nextPendingConnection();
  70. connect(client, SIGNAL(disconnected()), this, SLOT(client_close()));
  71. }
  72. void client_close()
  73. {
  74. client->close();
  75. client->deleteLater();
  76. client = NULL;
  77. }
  78. protected:
  79. virtual void
  80. timerEvent(QTimerEvent *event)
  81. {
  82. imageCapture->capture();
  83. // qDebug()<<"tttt";
  84. }
  85. private:
  86. QCamera *camera;
  87. QCameraViewfinder *viewfinder;
  88. QCameraImageCapture *imageCapture;
  89. QLabel *lb_pic;
  90. QTcpServer *myserver;
  91. QTcpSocket *client;
  92. };
  93. #endif // WIDGET_H
  1. #include "widget.h"
  2. #include <QHBoxLayout>
  3. #include <QHostAddress>
  4. Widget::Widget(QWidget *parent)
  5. : QWidget(parent)
  6. {
  7. camera = new QCamera("/dev/video0"); //"/dev/video0" 摄像头设备文件,视情况而定
  8. viewfinder = new QCameraViewfinder(this);
  9. viewfinder->setFixedSize(640,480);
  10. viewfinder->show();
  11. lb_pic = new QLabel(this);
  12. myserver = new QTcpServer(this);
  13. client = NULL;
  14. camera->setViewfinder(viewfinder);
  15. QHBoxLayout *hbox = new QHBoxLayout;
  16. hbox->addWidget(viewfinder);
  17. hbox->addWidget(lb_pic);
  18. this->setLayout(hbox);
  19. imageCapture = new QCameraImageCapture(camera);
  20. camera->setCaptureMode(QCamera::CaptureStillImage);
  21. connect(imageCapture, SIGNAL(imageCaptured(int,QImage)), this, SLOT(show_pic(int,QImage)));
  22. connect(myserver, SIGNAL(newConnection()), this, SLOT(accept_client()));
  23. this->startTimer(3);
  24. myserver->listen(QHostAddress::AnyIPv4, 8888);
  25. camera->start();
  26. }
  27. Widget::~Widget()
  28. {
  29. }

发文不通过只能写点”废话“了。学了一个星期的QT感觉其实不难,就是把一些封装好的类组合起来形成一些图形化界面。感觉还是挺好用,起码和C有相通性,唯一的难点应该在C++的语法上。所以会C++的同学应该更加的得心应手。挺好玩的,等学完驱动试试拿QT开发两个项目练练手。比如电视剧里男主给女主写的那个小猪闹钟,非常可爱以前不知道怎么下手做,学完QT我好像知道应该怎么写了。然后我还想做一个类似于QQ微信这种的聊天工具,可惜还不知道怎么用私网和私网通信。难道和女神之间搞点浪漫的东西还要租两台云服务器嘛,那也太扫兴了。现在这ip都是192.168开头的不能直接通信。听朋友说java有个内网透传技术是干这个的。不知道用C怎么实现。不过服务器我虽然买不起但是我打算自己买点件搭建一个服务器。应该会很有意思。


标签: c++ QT 网络编程

本文转载自: https://blog.csdn.net/qq_52479948/article/details/128824315
版权归原作者 宇努力学习 所有, 如有侵权,请联系我们删除。

“QT/C++——网络编程”的评论:

还没有评论