Qt 09TCP通信

1.TCPSocket

1.在工程文件中加入 network (QT += newwork) , 然后ctrl + s 保存一下

2.头文件引入TCP套接字类  
    #include <QTcpSocket>
    
3.在widget.h定义一个套接字指针,设置在成员里(因为都会用到)
     QTcpSocket *socket;  
     
4.构造套接字
    socket = new QtcpSocket(this);

5.按钮绑定信号
    连接按键槽函数:
    void Widget::on_btnCon_clicked()
    {
        //根据ip和端口号 连接到主机
         socket->connectToHost(ui->edtIP->text(),ui->edtPort->text().toInt());
    }
    断开连接按键槽函数:
    void Widget::on_btnDis_clicked()
    {
        //从主机断开连接
         socket->disconnectFromHost();
    }
        
6.发送数据
    检查数据是否为空,检查套接字是否有效
    void Widget::on_btnSend_clicked()
    {
        if(ui->msgSend->toPlainText().isEmpty())
            return;
            //判断套接字是否有效
        if(socket->isValid()){
                // 发送数据
            socket->write( ui->msgSend->toPlainText().toLatin1() );
        }
    }
 ------------------------------------ 
7.接收数据
 获取读缓存的有效字节数:
     bytesAvailable()
 读取缓冲区所有数据;
     readAll()
 如果每条数据有严格长度要求。就必须使用 bytesAvailable()read(n)函数配合使用
 ------------------------------------
 读的槽函数绑定:
 connect(socket, &QTcpSocket::readyRead, this, &Widget::recvData);
 只要socket读缓存 一有新数据,就立即触发 readyRead信号
 ------------------------------------
 槽函数:    
 void Widget::recvData()
 {
    qDebug() << socket->bytesAvailable();
    QByteArray data = socket->readAll();
    ui->msgRecv->append(data);
  }
 ------------------------------------
 8.检测客户端连接和断开连接
 信号:
     connected
     disconnected
 绑定槽函数:
     connect(socket, &QTcpSocket::connected,  [&]() {
        ui->lStatus->setText("已连接服务器");
    });
    connect(socket, &QTcpSocket::disconnected, [&](){
        ui->lStatus->setText("连接已断开");
    });
   

2.TcpServer

1.在工程文件中加入 network (QT += newwork) , 然后ctrl + s 保存一下

2.头文件引入TCP套接字类  
    #include <QTcpSocket>
    
3.在widget.h定义服务器对象
     QTcpServer *server;   
     
4.构建服务器对象
    server = new QTcpServer(this);
---------------------------------------------------------------------------    
5.设置监听套接字:
    (通过启动按钮转到槽函数---按下启动服务器的启动按钮,槽函数触发)
    
    void Widget::on_btnStart_clicked()
    {
                                    // 启动服务器,设置监听队列
        if(!server->listen(QHostAddress::AnyIPv4, ui->lineEdit->text().toInt())){
            ui->msgRecv->append("服务器启动失败");
            return;
        }
        ui->msgRecv->append("启动成功");
                        // 当监听队列中 有一个 新的客户端连接请求,立即触发 newConnection信号
        connect(server, &QTcpServer::newConnection, this, &Widget::newConnection);
    }
----------------------------------------------------------------------------
6.等待连接---在监听套接字里绑定的槽函数,一旦有客户端有连接请求的信号,立即触发该槽函数
    连接成功后,就会返回一个连接后的套接字,要先在成员的声明,用于接收该套接字
    QTcpSocket *socket;     //连接后的套接字

void Widget::newConnection()
{
    //    ui->msgRecv->append("新客户端");
    // nextPendingConnection():取出队列中的请求,建立通信管道,返回连接套接字的首地址
    socket = server->nextPendingConnection();
    if(!socket->isValid()){
        ui->msgRecv->append("通信建立失败");
        return;
    }
    // peerAddress():获取IP地址   peerPort():获取端口号
    ui->msgRecv->append(QString("%1 :%2").arg(socket->peerAddress().toString()).arg(socket->peerPort()));
    connect(socket, &QTcpSocket::readyRead, this, &Widget::recvData);
    connect(socket, &QTcpSocket::disconnected, [&](){
        ui->msgRecv->append("客户端已掉线");
        //断开信号与槽的连接
        disconnect(socket, &QTcpSocket::readyRead, this, &Widget::recvData);
    });
}
---------------------------------------------------------------------------   
7.发数据和收数据
void Widget::on_btnSend_clicked()
{
    if(socket->isValid()){
        socket->write(ui->msgSend->toPlainText().toLatin1());
    }
}
void Widget::recvData()
{
    QByteArray data = socket->readAll();
    ui->msgRecv->append(data);
}

3.eg:通过tcp发送图片(用小飞机发)—数据粘包问题

在这里插入图片描述

传数据就要用  QByteArray类

tcp数据发送,有自动纠错的功能,一次性发送的内容不一定是正确的,接收到的字节也不一定是正确的,
所以一定就不可以的readAll()来读取发送的图片数据,会导致数据粘包:

思路:
    先发图片上的长度,再发图片内容
    在发送图片之前,先一步将图片的大小发送过来,确定好图片的大小,以确保读取精准的字节数。
    读取图片时,如果少于之前发送的字节数,那么就不读取,等到字节数等于或大于之前的字节数说明
    缓冲区至少累计缓冲了一张图片,这个时候再读取
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值