QT/C++——网络编程

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

目录

一、基础知识复习

二、UDP

客户端

服务器

三、TCP

服务器

客户端

四、小项目

客户端

服务器


一、基础知识复习

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

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

 

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

二、UDP

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

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

客户端

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTextEdit>
#include <QLineEdit>
#include <QPushButton>
#include <QUdpSocket>
#include <QHostAddress>

class Widget : public QWidget
{
    Q_OBJECT
public slots:
    void senddata()
    {
        udpsock->writeDatagram(le->text().toStdString().c_str(), QHostAddress("192.168.3.27"), 8888);
    }

    void recvdata()
    {
        QByteArray datagram;
        datagram.resize(udpsock->pendingDatagramSize());
        QHostAddress sender;
        quint16 senderPort;

        udpsock->readDatagram(datagram.data(), datagram.size(),
                                          &sender, &senderPort);
        te->append(datagram);
    }
public:
    Widget(QWidget *parent = 0);
    ~Widget();
private:
    QTextEdit *te;
    QLineEdit *le;
    QPushButton *pb;

    QUdpSocket *udpsock;
};

#endif // WIDGET_H
#include "widget.h"
#include <QVBoxLayout>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    te = new QTextEdit;
    le = new QLineEdit;
    pb = new QPushButton("send");
    QVBoxLayout *vbox = new QVBoxLayout;
    vbox->addWidget(te);
    vbox->addWidget(le);
    vbox->addWidget(pb);
    setLayout(vbox);

    udpsock = new QUdpSocket;

    connect(pb, SIGNAL(clicked(bool)), this, SLOT(senddata()));
    connect(udpsock, SIGNAL(readyRead()), this, SLOT(recvdata()));
}

Widget::~Widget()
{

}

服务器

#ifndef UDPSERVER_H
#define UDPSERVER_H

#include <QObject>
#include <QUdpSocket>
#include <QDebug>

class udpServer : public QObject
{
    Q_OBJECT
public:
    explicit udpServer(QObject *parent = 0);
    void init()
    {
        udpSocket = new QUdpSocket(this);
        udpSocket->bind(QHostAddress::AnyIPv4, 8888);

        connect(udpSocket, SIGNAL(readyRead()),
                      this, SLOT(readPendingDatagrams()));
        qDebug()<<"init....";
    }
signals:

public slots:
    void readPendingDatagrams()
    {
        while (udpSocket->hasPendingDatagrams()) {
                  QByteArray datagram;
                  datagram.resize(udpSocket->pendingDatagramSize());
                  QHostAddress sender;
                  quint16 senderPort;

                  udpSocket->readDatagram(datagram.data(), datagram.size(),
                                          &sender, &senderPort);

                  //processTheDatagram(datagram);
                  qDebug()<<"recv: "<<datagram;

                  udpSocket->writeDatagram(datagram.data(), datagram.size(),
                                           sender, senderPort);
              }
    }

private:
    QUdpSocket *udpSocket;
};

#endif // UDPSERVER_H

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

三、TCP

服务器

#ifndef TCPSERVER_H
#define TCPSERVER_H

#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>
#include <QDebug>

class tcpServer : public QObject
{
    Q_OBJECT
public:
    explicit tcpServer(QObject *parent = 0);

signals:

public slots:
    void newconnected()
    {
        qDebug()<<"connected";
        clientsock = ser->nextPendingConnection();

        connect(clientsock, SIGNAL(readyRead()), this, SLOT(readdata()));
    }

    void readdata()
    {
        QByteArray buf =  clientsock->readAll();
        qDebug()<<"recv: "<<buf;
        clientsock->write(buf);
    }

private:
    QTcpServer *ser;
    QTcpSocket *clientsock;

};

#endif // TCPSERVER_H
#include "tcpserver.h"
#include <QHostAddress>

tcpServer::tcpServer(QObject *parent) : QObject(parent)
{
    ser = new QTcpServer;
    ser->listen(QHostAddress::AnyIPv4, 8888);
    connect(ser, SIGNAL(newConnection()), this, SLOT(newconnected()));

    ser->waitForNewConnection();
}

客户端

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTextEdit>
#include <QLineEdit>
#include <QPushButton>
#include <QTcpSocket>

class Widget : public QWidget
{
    Q_OBJECT
public slots:
    void senddata()
    {
        tcpsocket->write(le->text().toStdString().c_str());
    }

    void recvdata()
    {
        QByteArray buf = tcpsocket->readAll();
        te->append(buf);
    }
public:
    Widget(QWidget *parent = 0);
    ~Widget();
private:
    QTextEdit *te;
    QLineEdit *le;
    QPushButton *pb;

    QTcpSocket *tcpsocket;
};

#endif // WIDGET_H
#include "widget.h"
#include <QVBoxLayout>
#include <QHostAddress>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    te = new QTextEdit;
    le = new QLineEdit;
    pb = new QPushButton("send");

    QVBoxLayout *vbox = new QVBoxLayout;
    vbox->addWidget(te);
    vbox->addWidget(le);
    vbox->addWidget(pb);
    setLayout(vbox);

    tcpsocket = new QTcpSocket;
    //connect to server
    tcpsocket->connectToHost(QHostAddress("192.168.3.27"), 8888);

    connect(pb, SIGNAL(clicked(bool)), this, SLOT(senddata()));
    connect(tcpsocket, SIGNAL(readyRead()), this, SLOT(recvdata()));
}

Widget::~Widget()
{

}

四、小项目

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

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

客户端

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QLabel>
#include <QLineEdit>
#include <QTcpSocket>
#include <QPushButton>
#include <QHostAddress>
#include <QDebug>
#include <QPixmap>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();

public slots:
    void startv()
    {
        readsize = true;

        sockv = new QTcpSocket(this);
        connect(sockv, SIGNAL(readyRead()), this, SLOT(recv_show()));
        sockv->connectToHost(QHostAddress(leip->text()), atoi(leport->text().toStdString().c_str()));
        btstart->setText("STOP");
        leip->setDisabled(true);
        leport->setDisabled(true);

        disconnect(btstart, SIGNAL(clicked()), this, SLOT(startv()));
        connect(btstart, SIGNAL(clicked()), this, SLOT(stop()));
    }

    void stop()
    {
        sockv->close();
        sockv->deleteLater();

        disconnect(btstart, SIGNAL(clicked()), this, SLOT(stop()));
        connect(btstart, SIGNAL(clicked()), this, SLOT(startv()));

        leip->setDisabled(false);
        leport->setDisabled(false);
        btstart->setText("START");
    }

    void recv_show()
    {
        if(readsize){ //接收图片大小
            char buf[10] = {0};
            sockv->read(buf, 10);
            picsize = atoi(buf); //转成整形大小值
     //       qDebug()<<picsize;

            readsize = false;
        }
        else
        {
            if(sockv->bytesAvailable() < picsize) //等待图片内容接收完整
                return;

            char buf[640*480*3];
            sockv->read(buf, picsize);
            QPixmap pix;
            pix.loadFromData((uchar*)buf, picsize, "jpeg");
            lbvideo->setPixmap(pix);//切换照片

            readsize = true;
        }

    }

private:
    QLabel *lbvideo, *lbip, *lbport;
    QLineEdit *leip, *leport;
    QPushButton *btstart;

    QTcpSocket *sockv;

    bool readsize;
    int picsize;

};

#endif // WIDGET_H
#include "widget.h"
#include <QHBoxLayout>
#include <QVBoxLayout>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    lbvideo = new QLabel;
    lbvideo->setFixedSize(640,480);
    lbvideo->setScaledContents(true);
    lbip = new QLabel("IP");
    lbport = new QLabel("PORT");

    leip = new QLineEdit("192.168.3.27");
    leport = new QLineEdit("8888");

    btstart = new QPushButton("START");

    QHBoxLayout *hbox = new QHBoxLayout;
    hbox->addWidget(lbip);
    hbox->addWidget(leip);
    hbox->addWidget(lbport);
    hbox->addWidget(leport);
    hbox->addWidget(btstart);

    QVBoxLayout *vbox = new QVBoxLayout;
    vbox->addLayout(hbox);
    vbox->addWidget(lbvideo);

    setLayout(vbox);

    connect(btstart, SIGNAL(clicked()), this, SLOT(startv()));
}

Widget::~Widget()
{

}

服务器

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QCamera>
#include <QCameraViewfinder>
#include <QCameraImageCapture>
#include <QLabel>
#include <QTimerEvent>
#include <QDebug>
#include <QPixmap>
#include <QTcpServer>
#include <QTcpSocket>
#include <QTemporaryFile>
#include <QFile>
#include <QBuffer>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();
public slots:
    void show_pic(int i, QImage img)
    {

        QPixmap pix(1920, 1080);
#if 1
        pix.fill(Qt::red);
        pix = pix.fromImage(img);
        lb_pic->setPixmap(pix);
#else
        lb_pic->setPixmap(QPixmap::fromImage(img));

#endif
//        qDebug()<<i;


        if(client&&client->isWritable())
        {
//            qDebug()<<"sending "<<pix.size();
#if 0
            pix.save("tem.jpg","jpeg");
//             qDebug()<<"saveed";
            QFile tem("tem.jpg");
            tem.open(QIODevice::ReadOnly);

#else
            QBuffer tem;
            pix.save(&tem, "jpeg");
#endif
            char buf[10] = {0};
 //           qDebug()<<"size: "<<buf;
            sprintf(buf, "%d", tem.size());
  //          qDebug()<<"size: "<<buf;
            client->write(buf, 10);//发大小大小值先转换成字符串装在固定的10个字节的buff中发送
  //          qDebug()<<"size ok";
#if 0
            QByteArray data = tem.readAll();           
#else
            QByteArray data(tem.buffer());
#endif
            client->write(data);//发图片内容
   //          qDebug()<<"finish";
             tem.close();
        }
    }

    void accept_client()
    {
        if(NULL != client)
        {
            client->close();
            client->deleteLater();
        }
        client = myserver->nextPendingConnection();
        connect(client, SIGNAL(disconnected()), this, SLOT(client_close()));
    }

    void client_close()
    {
        client->close();
        client->deleteLater();
        client = NULL;
    }
protected:
    virtual void
    timerEvent(QTimerEvent *event)
    {
        imageCapture->capture();
//        qDebug()<<"tttt";
    }

 private:
    QCamera *camera;
    QCameraViewfinder *viewfinder;
    QCameraImageCapture *imageCapture;
    QLabel *lb_pic;

    QTcpServer *myserver;
    QTcpSocket *client;
};

#endif // WIDGET_H
#include "widget.h"
#include <QHBoxLayout>
#include <QHostAddress>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    camera = new QCamera("/dev/video0"); //"/dev/video0" 摄像头设备文件视情况而定
    viewfinder = new QCameraViewfinder(this);
    viewfinder->setFixedSize(640,480);
    viewfinder->show();

      lb_pic = new QLabel(this);
      myserver = new QTcpServer(this);
      client = NULL;

    camera->setViewfinder(viewfinder);
      QHBoxLayout *hbox = new QHBoxLayout;
        hbox->addWidget(viewfinder);
      hbox->addWidget(lb_pic);

      this->setLayout(hbox);

      imageCapture = new QCameraImageCapture(camera);

      camera->setCaptureMode(QCamera::CaptureStillImage);

      connect(imageCapture, SIGNAL(imageCaptured(int,QImage)), this, SLOT(show_pic(int,QImage)));
      connect(myserver, SIGNAL(newConnection()), this, SLOT(accept_client()));

      this->startTimer(3);
      myserver->listen(QHostAddress::AnyIPv4, 8888);
      camera->start();
}

Widget::~Widget()
{

}

---------------------------------------------------------------------------------------------------------------------------------

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

---------------------------------------------------------------------------------------------------------------------------------

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: c++