QT基础(八)----TCP通信 & UDP通信

本文详细介绍了QT库中实现TCP和UDP通信的基本步骤,包括建立一个服务器与客户端间的连接,以及如何在程序中添加IP地址选择窗口进行通信。同时,还探讨了UDP通信的特点和使用方法。
摘要由CSDN通过智能技术生成

一 一个服务器和一个客户端之间的通信

主窗口MyMainWindow.h

#ifndef MYMAINWINDOW_H
#define MYMAINWINDOW_H

#include <QWidget>

class MyMainWindow : public QWidget
{
    Q_OBJECT
public:
    explicit MyMainWindow(QWidget *parent = 0);

signals:

public slots:
};

#endif // MYMAINWINDOW_H

MyMainWindow.cpp

#include "MyMainWindow.h"
#include<QApplication>
#include"MyTcpClient.h"
#include<MyTcpServer.h>

MyMainWindow::MyMainWindow(QWidget *parent) : QWidget(parent)
{

}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    MyTcpServer s; s.setWindowTitle("Sever"); s.show();
    MyTcpClient c; c.setWindowTitle("Client"); c.show();

    app.exec();
}

服务器端口MyTcpServer.h

#ifndef MYTCPSERVER_H
#define MYTCPSERVER_H

#include <QWidget>
#include<QTcpServer>    //需要在.pro文件中加QT += network
#include<QTcpSocket>
#include<QTextBrowser>

class MyTcpServer : public QWidget
{
    Q_OBJECT
public:
    explicit MyTcpServer(QWidget *parent = 0);

    QTcpServer *_server;
    QTcpSocket *_socket;
    QTextBrowser *_show;

signals:

public slots:
    void slotNewConnection();
    void slotReadyRead();
};

#endif // MYTCPSERVER_H

服务器端口MyTcpServer.cpp

#include "MyTcpServer.h"
#include<QByteArray>
#include<QHBoxLayout>
#include<QNetworkInterface>     //选择网址

MyTcpServer::MyTcpServer(QWidget *parent) : QWidget(parent)
{
    //创建服务器用于监听
    _server = new QTcpServer;
    //第一个参数为网址,第二个参数为端口
    _server->listen(QHostAddress::Any, 9988);       //建立监听机制和端口,现在监听的是使用的IP地址
    //通过一个槽函数建立起一个新的监听,当有一个新的连接时,触发槽的内容
    connect(_server, SIGNAL(newConnection()), this, SLOT(slotNewConnection()));

    _show = new QTextBrowser;
    QHBoxLayout *layout = new QHBoxLayout(this);
    layout->addWidget(_show);
}

void MyTcpServer::slotNewConnection()
{
    //获取多个TcpSocket,判断是否有未处理的连接,如果有就调用新的连接来处理连接的数据
    while(_server->hasPendingConnections())
    {
        _show->append("new connection...");
        //只要有新的连接就要建立一个TcpSocket
        _socket = _server->nextPendingConnection();
        connect(_socket, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
    }
}

void MyTcpServer::slotReadyRead()
{
    //如果_socket中还有数据,就需要读出来
    while(_socket->bytesAvailable() > 0)
    {
        _show->append("Data arrived... ");
        //读出数据中所有的数据,通过readAll读取所有数据
        QByteArray buf = _socket->readAll();
        _show->append(buf);
    }
}

客户端端口MyTcpClient.h

#ifndef MYTCPCLIENT_H
#define MYTCPCLIENT_H

#include <QWidget>
#include<QTcpSocket>
#include<QLineEdit>

class MyTcpClient : public QWidget
{
    Q_OBJECT
public:
    explicit MyTcpClient(QWidget *parent = 0);

    QTcpSocket *_socket;
    QLineEdit *_edit;

signals:

public slots:
    void slotButtonClick();
};

#endif // MYTCPCLIENT_H

客户端端口MyTcpClient.cpp

#include "MyTcpClient.h"
#include<QHBoxLayout>
#include<QPushButton>

MyTcpClient::MyTcpClient(QWidget *parent) : QWidget(parent)
{
    _socket = new QTcpSocket(this);
    _socket->connectToHost("127.0.0.1", 9988);
    _edit = new QLineEdit;

    QHBoxLayout *layout = new QHBoxLayout(this);
    layout->addWidget(_edit);

    //通过截取return按键发送消息
    connect(_edit, SIGNAL(returnPressed()), this, SLOT(slotButtonClick()));

    QPushButton *button = new QPushButton("Submit");
    layout->addWidget(button);

    //通过点击Enter按键发送消息
    connect(button, SIGNAL(clicked()), this, SLOT(slotButtonClick()));
}

void MyTcpClient::slotButtonClick()
{
    QString strText = _edit->text();
    if(strText.isEmpty())
        return;
    else
        _socket->write(strText.toUtf8());       //通过utf8格式转换为ByteArray格式
    //将输入框制空
//    _edit->setText("");
    _edit->clear();

}

运行结果:


二 在上述程序的基础上增加IP地址选择窗口

头文件ChooseInterface.h,继承自QDialog

#ifndef CHOOSEINTERFACE_H
#define CHOOSEINTERFACE_H

#include <QDialog>
#include<QComboBox>

class ChooseInterface : public QDialog
{
    Q_OBJECT
public:
    explicit ChooseInterface(QWidget *parent = 0);

    QComboBox *_combox;
    QString _strSlelect;        //将_combox中选择的内容保存到_strSelect中


signals:

public slots:
    void slotsSelectAddress(QString str);

};

#endif // CHOOSEINTERFACE_H

源文件ChooseInterface.cpp

#include "ChooseInterface.h"
#include<QNetworkInterface>
#include<QVBoxLayout>

ChooseInterface::ChooseInterface(QWidget *parent) : QDialog(parent)
{
    //get all interface,获取所有的IP地址
    QList<QHostAddress> addrList = QNetworkInterface::allAddresses();

    //返回所有的网口
//    QList<QNetworkInterface> intefaceList =  QNetworkInterface::allInterfaces();
    //获取网口的入口地址
//    QList<QNetworkAddressEntry> entryList = intefaceList.at(0).addressEntries();
    //entryList又可以获取更详细的网络地址、网络地址等等
//   QHostAddress add =  entryList.at(0).broadcast();

    _combox = new QComboBox(this);
    QVBoxLayout *layout = new QVBoxLayout(this);
    layout->addWidget(_combox);

    foreach(QHostAddress addr, addrList)
    {
        //先转为IPV4地址,再讲IPV4地址转化为字符串,如果是0就不用添加
        quint32 tempAddr = addr.toIPv4Address();

        if(tempAddr == 0)
            continue;
        else
            _combox->addItem(QHostAddress(tempAddr).toString());
    }

    //选择框发生变化时,返回其内容
    connect(_combox, SIGNAL(currentIndexChanged(QString)),this, SLOT(slotsSelectAddress(QString)));
}

void ChooseInterface::slotsSelectAddress(QString str)
{
    this->_strSlelect = str;
}

头文件MyTcpClient.h

#ifndef MYTCPCLIENT_H
#define MYTCPCLIENT_H

#include <QWidget>
#include<QTcpSocket>
#include<QLineEdit>

class MyTcpClient : public QWidget
{
    Q_OBJECT
public:
    explicit MyTcpClient(QWidget *parent = 0);

    QTcpSocket *_socket;
    QLineEdit *_edit;

signals:

public slots:
    void slotButtonClick();
};

#endif // MYTCPCLIENT_H

源文件MyTcpClient.cpp

#include "MyTcpClient.h"
#include<QHBoxLayout>
#include<QPushButton>

MyTcpClient::MyTcpClient(QWidget *parent) : QWidget(parent)
{
    _socket = new QTcpSocket(this);
    _socket->connectToHost("127.0.0.1", 9988);
    _edit = new QLineEdit;

    QHBoxLayout *layout = new QHBoxLayout(this);
    layout->addWidget(_edit);

    //通过截取return按键发送消息
    connect(_edit, SIGNAL(returnPressed()), this, SLOT(slotButtonClick()));

    QPushButton *button = new QPushButton("Submit");
    layout->addWidget(button);

    //通过点击Enter按键发送消息
    connect(button, SIGNAL(clicked()), this, SLOT(slotButtonClick()));
}

void MyTcpClient::slotButtonClick()
{
    QString strText = _edit->text();
    if(strText.isEmpty())
        return;
    else
        _socket->write(strText.toUtf8());       //通过utf8格式转换为ByteArray格式
    //将输入框制空
//    _edit->setText("");
    _edit->clear();

}

头文件MyTcpServer.h

#ifndef MYTCPSERVER_H
#define MYTCPSERVER_H

#include <QWidget>
#include<QTcpServer>    //需要在.pro文件中加QT += network
#include<QTcpSocket>
#include<QTextBrowser>

class MyTcpServer : public QWidget
{
    Q_OBJECT
public:
    explicit MyTcpServer(QWidget *parent = 0);

    QTcpServer *_server;
    QTcpSocket *_socket;
    QTextBrowser *_show;

signals:

public slots:
    void slotNewConnection();
    void slotReadyRead();
};

#endif // MYTCPSERVER_H

源文件:MyTcpServer.cpp

#include "MyTcpServer.h"
#include<QByteArray>
#include<QHBoxLayout>
#include<QNetworkInterface>     //选择网址
#include"ChooseInterface.h"
#include<QMessageBox>

MyTcpServer::MyTcpServer(QWidget *parent) : QWidget(parent)
{
    //创建服务器用于监听
    _server = new QTcpServer;

    //在监听之前就要选取IP地址
    ChooseInterface* dlg = new ChooseInterface(this);
    dlg->exec();

    //提示选择的IP地址
    QMessageBox::information(NULL,"You select the ip:", dlg->_strSlelect);
    //为新选的地址分配服务
    _server->listen(QHostAddress(dlg->_strSlelect), 9988);

    //第一个参数为网址,第二个参数为端口
 //   _server->listen(QHostAddress::Any, 9988);       //建立监听机制和端口,现在监听的是使用的IP地址
    //通过一个槽函数建立起一个新的监听,当有一个新的连接时,触发槽的内容
    connect(_server, SIGNAL(newConnection()), this, SLOT(slotNewConnection()));

    _show = new QTextBrowser;
    QHBoxLayout *layout = new QHBoxLayout(this);
    layout->addWidget(_show);
}

void MyTcpServer::slotNewConnection()
{
    //获取多个TcpSocket,判断是否有未处理的连接,如果有就调用新的连接来处理连接的数据
    while(_server->hasPendingConnections())
    {
        _show->append("new connection...");
        //只要有新的连接就要建立一个TcpSocket
        _socket = _server->nextPendingConnection();
        connect(_socket, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
    }
}

void MyTcpServer::slotReadyRead()
{
    //如果_socket中还有数据,就需要读出来
    while(_socket->bytesAvailable() > 0)
    {
        _show->append("Data arrived... ");
        //读出数据中所有的数据,通过readAll读取所有数据
        QByteArray buf = _socket->readAll();
        _show->append(buf);
    }
}

MyMainWindow.h

#ifndef MYMAINWINDOW_H
#define MYMAINWINDOW_H

#include <QWidget>

class MyMainWindow : public QWidget
{
    Q_OBJECT
public:
    explicit MyMainWindow(QWidget *parent = 0);

signals:

public slots:
};

#endif // MYMAINWINDOW_H

源文件MyMainWindow.cpp

#include "MyMainWindow.h"
#include<QApplication>
#include"MyTcpClient.h"
#include<MyTcpServer.h>

MyMainWindow::MyMainWindow(QWidget *parent) : QWidget(parent)
{

}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    MyTcpServer s; s.setWindowTitle("Sever"); s.show();
    MyTcpClient c; c.setWindowTitle("Client"); c.show();

    app.exec();
}

运行结果:


3 UDP通信

头文件MyUdp1.h
#ifndef MYUDP1_H
#define MYUDP1_H

#include <QWidget>
#include<QUdpSocket>
#include<QTextBrowser>

class MyUdp1 : public QWidget
{
    Q_OBJECT
public:
    explicit MyUdp1(QWidget *parent = 0);

    QUdpSocket *_udp;
    QTextBrowser *_show;

signals:

public slots:
    void slotReadyRead();
};

#endif // MYUDP1_H

源文件MyUdp1.cpp

#include "MyUdp1.h"
#include<QByteArray>
#include<QDebug>
#include<QTimer>
#include<QDateTime>
#include<QHostAddress>
#include<QVBoxLayout>

//udp效率高,每次发送的消息,交换机将udp消息排到头,udp丢了就丢了,tcp丢了就会重发

MyUdp1::MyUdp1(QWidget *parent) : QWidget(parent)
{
    //内存被托管(加入父类中,如将该窗口加入到this中)之后
    //每一个对象都有一个delete和deleteLater函数,delete立即释放,deleteLate等一会合适了再删除


    _show = new QTextBrowser;

    QVBoxLayout *layout = new QVBoxLayout(this);
    layout->addWidget(_show);

    _udp = new QUdpSocket;
    _udp->bind(10001);//绑定一个端口

    connect(_udp, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));

    //每隔2秒给对方发送一个信息
    QTimer *timer = new QTimer;
    timer->setInterval(1000);
    timer->start();
    connect(timer, &QTimer::timeout, [this](){
        quint64 timestamp = QDateTime::currentMSecsSinceEpoch();
        QString str = QString::number(timestamp);// 将整数转化为字符串
#if 0
       _udp->writeDatagram(str.toUtf8(), QHostAddress("127.0.0.1"), 10002);  //转为ByteArray发送
#endif

#if 0
        _udp->writeDatagram(str.toUtf8(), QHostAddress::Broadcast, 10002);//通过10002端口进行广播
#endif
        //多播广播
        _udp->writeDatagram(str.toUtf8(), QHostAddress("224.1.1.131"), 10002);
    });
}

void MyUdp1::slotReadyRead()
{
    while(_udp->hasPendingDatagrams())
    {
        quint32 datagramSize = _udp->pendingDatagramSize();//获取报文大小
        QByteArray buffer(datagramSize, 0);//申请空间大小
        _udp->readDatagram(buffer.data(), buffer.size());//读取报文内容
//        qDebug()<<buffer;//打印报文内容
        _show->append(buffer);
    }
}

头文件MyDup2.h

#ifndef MYUDP2_H
#define MYUDP2_H

#include <QWidget>
#include<QUdpSocket>
#include<QTextBrowser>

class MyUdp2 : public QWidget
{
    Q_OBJECT
public:
    explicit MyUdp2(QWidget *parent = 0);

    QUdpSocket *_udp;
    QTextBrowser *_show;
signals:

public slots:
    void slotReadyRead();
};

#endif // MYUDP2_H

源文件MyDup2.cpp
#include "MyUdp2.h"
#include<QByteArray>
#include<QDebug>
#include<QTimer>
#include<QDateTime>
#include<QHostAddress>
#include<QVBoxLayout>

MyUdp2::MyUdp2(QWidget *parent) : QWidget(parent)
{

    _show = new QTextBrowser;

    QVBoxLayout *layout = new QVBoxLayout(this);
    layout->addWidget(_show);

    _udp = new QUdpSocket;
    _udp->bind(QHostAddress::AnyIPv4,10002);//绑定一个端口
    _udp->joinMulticastGroup(QHostAddress("224.1.1.131"));//加入多播

    connect(_udp, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));

    //每隔2秒给对方发送一个信息
    QTimer *timer = new QTimer;
    timer->setInterval(1000);
    timer->start();
    connect(timer, &QTimer::timeout, [this](){
        quint64 timestamp = QDateTime::currentMSecsSinceEpoch();
        QString str = QString::number(timestamp);// 将整数转化为字符串
        _udp->writeDatagram(str.toUtf8(), QHostAddress("127.0.0.1"), 10001);  //转为ByteArray发送
    });
}

void MyUdp2::slotReadyRead()
{
    while(_udp->hasPendingDatagrams())
    {
        quint32 datagramSize = _udp->pendingDatagramSize();//获取报文大小
        QByteArray buffer(datagramSize, 0);//申请空间大小
        _udp->readDatagram(buffer.data(), buffer.size());//读取报文内容
//        qDebug()<<buffer;//打印报文内容
        _show->append(buffer);
    }
}


运行结果:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值