IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> QT学习 网络tcp+udp -> 正文阅读

[网络协议]QT学习 网络tcp+udp

准备工作

  • PRO
QT       += network

  • 头文件
#include <QTcpSocket> 

#include <QTcpServer> 

#include <QUdpSocket> 

tcp客户端只需要QTcpSocket。

tcp服务端,需要QTcpServer 来监听,QTcpSocket来管理客户端连接

udp需要QUdpSocket

TCP 客户端

打开?

   QTcpSocket m_handle;

   //连接信号槽,接收消息

   QObject::connect(&m_handle, &QTcpSocket::readyRead, this, &XXX::slotReadyRead);
   // 连接断开响应

   QObject::connect(&m_handle, &QTcpSocket::disconnected, this, &XXX::slotDisconnected);

   //套接字错误响应
    QObject::connect(&m_handle, SIGNAL(error(QAbstractSocket::SocketError)),

                     this, SLOT(slotError(QAbstractSocket::SocketError)));


   //连接服务器

    m_handle.connectToHost(IP, PORT);


   //等待连接成功

   if(!m_handle.waitForConnected(1000))

   {

       qDebug() << "Connection failed!";

   }

   qDebug() << "Connect successfully!";

关闭

m_handle.disconnectFromHost();

QObject::disconnect(&m_handle, 0, 0, 0);

发送

    QByteArray sendData;

    qint64 written = m_handle.write(sendData);

    m_handle.flush();

接收槽函数

void XXX::slotReadyRead()

{

    QByteArray buffer = m_handle.readAll();
    qDebug() << buffer;

   // ……

}

断开槽函数
?

void XXX::slotDisconnected()

{

   //取消已有的连接

    m_handle.abort();

   qDebug() << "Disconnected!";

}

出错槽函数

void XXX::slotError(QAbstractSocket::SocketError)

{

   //取消已有的连接

    m_handle.abort();

}

tcp服务端

比客户端多了? 客户端监听 以及? 已连接客户端的维护

一般的实现形式

启动监听


?

   QTcpServer m_server;


   if (m_server.listen(QHostAddress::Any, port)) {

       // 连接信号槽,当有新的客户端连接时响应

       QObject::connect(&m_server, &QTcpServer::signal_incomingConnection, this, &XXX::slot_incomingConnection);

       qDebug() << "Server listenning!";

   }

   else {

       qDebug() << m_server.errorString();

   }
   

客户端连接槽函数

QList<QTcpSocket *> m_list;

void XXX::slot_incomingConnection() //响应客户端连接请求的函数

{

   //获取连接的客户端

    QTcpSocket *client = tcpServer.nextPendingConnection();

    m_list.append(client );

   //连接信号槽,用于接收客户端消息

   connect(client , SIGNAL(readyRead()), this, SLOT(slot_readyRead()));

}

客户端接收槽函数,可以发现无法直接知道是哪个客户端发来的消息

void xxx::slot_readyRead()

{
// 遍历所有客户端,检查谁有待读取的消息

   for (int i = 0; i < m_list.size(); i++)

   {


       if (m_list.at(i)->bytesAvailable())

       {

           //读取消息并保存

            QByteArray buffer = m_list.at(i)->readAll();

           qDebug() << buffer;

       }

   }

}

发送

void XXX::send(int i, const QByteArray &buf)

{

        m_list.at(i)->write(buf);

}

维护客户端连接情况

       // 当前连接数
       unsigned int size = m_list.size();

       //删除断开的客户端

       for (unsigned int i = 0; i < size ; i++)

       {

           // 判断当前客户端是否未连接

           if (m_list.at(i)->state() == QAbstractSocket::UnconnectedState)

           {

                m_list.removeAt(i);

               --i;

               --size ;

           }

       }

派生类形式

由于正常的使用qtcpsocket,当接收到消息或者当断开连接时无法知道是哪个客户端发起的。为了解决这个问题,可以自QTcpSocket派生子类。

qtcpserver类的正常使用,需nextPendingConnection获取新连接的客户端,这个在多个客户端同时发起时可能存在问题。也可以自QTcpServer派生子类来解决。

具体操作是

1、在qtcpserver派生类中增加一个信号(包含描述符和套接字),并在incomingConnection重载函数中emit。

2、在qtcpsocket派生类中改写信号(增加描述符和套接字),绑定原始信号(readyRead、disconnected等),在槽函数中emit改写的信号。

由于信号都带上了描述符和socket,绑定的槽函数直接就能知道发起的客户端描述符和套接字。

UDP

udp比较简单,绑定端口,就可以收发了。

打开

QUdpSocket m_handle;


    m_handle.bind(port,QUdpSocket::ShareAddress);
    // 绑定槽函数,接收消息

   connect(&m_handle,&QUdpSocket::readyRead,this,&XXX::slot_readyRead);

   qDebug() << "Bind successfully!";

发送

QByteArray sendData;


   

    qint64 written = m_handle.writeDatagram(sendData.data(),

                                            sendData.size(),

                                           QHostAddress(ip),

                                            port);


    m_handle.flush();

接收槽函数

void XXX::slot_readyRead()

{

    QByteArray buffer;


   //有未处理的消息

   if(m_handle.hasPendingDatagrams()){

        buffer.resize(m_handle.pendingDatagramSize());

        m_handle.readDatagram(buffer.data(),buffer.size());
        qDebug() << buffer;
        //……

   }

}

示例

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-09-04 01:45:01  更:2022-09-04 01:45:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 11:42:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码