Qt day7 UPD/TCP网络编程

一、UDP客户端

widget.h:

套接字头文件 槽函数 套接字

#include <QUdpSocket>

private slots:
    void on_pb_send_clicked();

    void on_pb_clear_clicked();

private:
    QUdpSocket *socket;

widget.cpp:

//1.new套接字 别忘了指定父对象this
    socket = new QUdpSocket(this); 
//2.连接socket信号 与 槽函数(拉姆达表达式)
//2.1 读取并显示到接收区    readyread--表示有对端的数据到达
    connect(socket,&QUdpSocket::readyRead,[=](){
        while(socket->hasPendingDatagrams()){    //循环读取
            QByteArray datagram;
            datagram.resize(socket->pendingDatagramSize());//根据接收数据的长度调整字节数组的长度
            socket->readDatagram(datagram.data(),datagram.size());//读数据
            ui->te_recv->append(datagram);//显示到接收区
        }
    });

//3.发送数据按钮
//3.1判空(地址、端口、内容)
//3.2把文本编辑器的内容转化并写入套接字
void Widget::on_pb_send_clicked()
{
    if(ui->le_ip->text().isEmpty() ||
       ui->le_port->text().isEmpty()){
        QMessageBox::information(this,"服务器地址或端口错误!","服务器地址和端口不能为空!");
        return;
    }
    if(ui->te_send->toPlainText().isEmpty()){
        QMessageBox::information(this,"发送内容错误!","发送内容不能为空!");
        return;
    }

    //发送数据到服务器的地址和端口
    //文本编辑器的纯文本 latin..............
    if(socket->writeDatagram(ui->te_send->toPlainText().toLocal8Bit(),//toLatin1()可能只支持英文
                          QHostAddress(ui->le_ip->text()),
                          ui->le_port->text().toUShort()) == -1){
        qDebug()<<"客户端发送数据失败";
    }
    else
        qDebug()<<"客户端发送数据成功";
}

void Widget::on_pb_clear_clicked()
{
    ui->te_recv->clear();
}

二、UDP服务器

widget.h:

头文件
转到槽函数
对象
#include <QUdpSocket>
private slots:
    void on_pb_send_clicked();

    void on_pb_clear_clicked();
private:
    Ui::Widget *ui;
    QUdpSocket *socket;
    QHostAddress ip;//对端的IP地址
    quint16 port;//对端的端口号

wifget.cpp

1.new一个套接字
2.bind绑定本机任意IP地址,绑定端口
3.连接信号与槽函数
3.1 循环读取数据并显示到接收区
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    setWindowTitle("UDP服务器");
    socket = new QUdpSocket(this);
    socket->bind(QHostAddress::AnyIPv4,8848);   //绑定!!本机任意IPv4地址和8848端口
    //连接信号与槽函数
    connect(socket,&QUdpSocket::readyRead,[=](){
        //只要还有待处理的数据,就不断读取
        while(socket->hasPendingDatagrams()){   //haspendingdatagrams返回布尔值
            QByteArray  datagram;
            //根据接收数据的大小调整字节数组的大小
            datagram.resize(socket->pendingDatagramSize());
            socket->readDatagram(datagram.data(),datagram.size(),
                                 &ip,&port);//获得数据的同时,保存IP和端口!!!
            //显示到接收区
            ui->te_recv->append(QString::fromLocal8Bit(datagram));//转换
            ui->pb_send->setEnabled(true);//激活发送按钮
        }
    });
}
4.发送按钮
4.1判空    
4.2发送
void Widget::on_pb_send_clicked()
{
    if(ui->te_send->toPlainText().isEmpty())  //文本编辑框没有text()
    {
        QMessageBox::warning(this,"发送数据错误!","发送数据不能为空");
        return;
    }
    if(socket->writeDatagram(ui->te_send->toPlainText().toLocal8Bit(),
                             ip,port) == -1){
        qDebug()<<"服务器发送数据失败";
    }
    else{
        qDebug()<<"服务器发送数据成功";
    }
}

void Widget::on_pb_clear_clicked()
{
    ui->te_recv->clear();
}

三、TCP客户端

widget.h:

头文件、转到槽函数、套接字

widget.cpp:

#include <QHostAddress>
构造函数:
socket = new QTcpSocket(this);//别忘记设置父对象this

    //连接信号与槽函数
    //1.socket 发送 连接成功 的信号 connected
    connect(socket,&QTcpSocket::connected,[=](){
        ui->pb_connect->setText("断开连接");
        ui->pb_send->setEnabled(true);
    });
    //2.socket 发送 连接断开 的信号 disconnected
    connect(socket,&QTcpSocket::disconnected,[=](){
        ui->pb_connect->setText("连接");
        ui->pb_send->setEnabled(false);
    });
    //3.socket 发送 数据就绪 的信号 readtRead
    connect(socket,&QTcpSocket::readyRead,[=](){
        QByteArray data;
        data = socket->readAll();   //socket->readAll()返回QByteArray
        if(!data.isEmpty()){
            ui->te_recv->append(QString::fromLocal8Bit(data));//QByteArray转化为QString放到接收区
        }
    });
    //4.socket 发送 错误 的信号error       模板类Qoverload的使用QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error)
    connect(socket,QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error),[=](QAbstractSocket::SocketError socketError){
        qDebug()<< "socket error = "<<socketError;//打印连接失败的信息
        if(socket->state() != QAbstractSocket::ConnectedState){
            socket->connectToHost(QHostAddress(ui->le_ip->text()),ui->le_port->text().toUShort());
        }//主动向服务器发起连接.这样就只需要点一次连接
    });

连接按钮(连接上了变成断开连接)
//判空、发送连接请求
void Widget::on_pb_connect_clicked()
{
    if(ui->pb_connect->text() == "连接"){
        QString ip = ui->le_ip->text();
        QString port = ui->le_port->text();
        if(ip.isEmpty() || port.isEmpty()){
            QMessageBox::warning(this,"连接错误!","服务器IP或端口不能为空!");
            return;
        }
        //4.向 服务器 发起 连接请求
        socket->connectToHost(QHostAddress(ip),port.toUShort());
    }
    else
        socket->close();
}

发送按钮
//判空、发送
void Widget::on_pb_send_clicked()
{
    if(ui->te_send->toPlainText().isEmpty()){
        QMessageBox::information(this,"发送内容错误!","发送内容不能为空!");
        return;
    }

    //5.发送数据到对端
    if (socket->write(ui->te_send->toPlainText().toLocal8Bit()) == -1){
        qDebug()<<"客户端发送数据失败";
    }
    else{
        qDebug()<<"客户端发送数据成功";
    }
}

void Widget::on_pb_clear_clicked()
{
    ui->te_recv->clear();
}

四、TCP服务器

widget.h:        两个头文件 一个用于TCP连接 一个用于通信的套接字

#include <QTcpSocket>
#include <QTcpServer>   //头文件

private slots:
    void on_pb_send_clicked();

    void on_pb_clear_clicked();

private:
    Ui::Widget *ui;
    QTcpServer *server;//同于TCP连接
    QTcpSocket *socket;//用于通信的套接字

widget.cpp:

#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>
#include <QDebug>
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    setWindowTitle("TCP服务器");
    server = new QTcpServer(this);
    //socket = new QTcpSocket(this);    服务端的socket是建立连接后返回的(同网络编程)

    //1.监听
    server->listen(QHostAddress::AnyIPv4,8848);//监听本地地址和端口

    //连接服务器的信号与槽函数
    //2.server 发送的 新的连接 已经建立 的信号
    connect(server,&QTcpServer::newConnection,[=](){
        while(server->hasPendingConnections()){//连接建立好了
            qDebug()<<"incoming connection";
            //获取一个新的通信套接字
            socket = server->nextPendingConnection();
            ui->pb_send->setEnabled(true);

            //连接 通信套接字的 信号与槽函数
            //socket通信套接字 发送的 连接断开 的信号
            connect(socket,&QTcpSocket::disconnected,[=](){
                ui->pb_send->setEnabled(false);
            });
            connect(socket,&QTcpSocket::readyRead,[=](){
                QByteArray data;
                data = socket->readAll();   //返回QByteArray
                ui->te_recv->append(QString::fromLocal8Bit(data));//转换
            });
        }
        qDebug()<<"incoming connection 2";
    });


}

Widget::~Widget(){delete ui;}

void Widget::on_pb_send_clicked()
{
    if(ui->te_send->toPlainText().isEmpty()){
        QMessageBox::warning(this,"发送内容错误","发送内容不能为空");
        return;
    }
    //使用utf8的编码,支持更多的语言
    if (-1 == socket->write(ui->te_send->toPlainText().toLocal8Bit())){
        qDebug()<<"TCP服务器发送数据失败";
    }
    else
        qDebug()<<"TCP服务器发送数据成功";
}
void Widget::on_pb_clear_clicked()
{
    ui->te_recv->clear();
}

目前处在硬记步骤和函数的状态  也不好改进质量

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值