qt tcpsocket 接收数据_如何给微信好友发送指定位置

qt tcpsocket 接收数据_如何给微信好友发送指定位置在网络应用中,有时候我们会遇到这样的问题,用TCP不断的接收和发送不同类型的数据,数据大小,格式都不相同,起初看了qt的例子,按照例子写的程序效果相当的不好,尤其是在连续发送大数据的时候,接收端根本无法判断数据是否完整了,也不知道什么时候取读取,经过各种折腾加上看qt源码,总结出了这个方法,发送的时候,要先发送这个数据序列化后的大小,然后发送这个数据本身,接收端,首先收到了要接收数据的大小,心里有

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

         在网络应用中,有时候我们会遇到这样的问题,用TCP不断的接收和发送不同类型的数据,数据大小,格式都不相同,起初看了qt的例子,按照例子写的程序效果相当的不好,尤其是在连续发送大数据的时候,接收端根本无法判断数据是否完整了,也不知道什么时候取读取,经过各种折腾加上看qt源码,总结出了这个方法,发送的时候,要先发送这个数据序列化后的大小,然后发送这个数据本身,接收端,首先收到了要接收数据的大小,心里有数了,等到缓存区的数据大于或者等于要接收数据大小的时候,再过去取数据,就保证了数据的正确完整和及时。最开始的时候,用QByteArry发送数据,先发送了这个QByteArry的size,然后接着发送了这个QByteArry,结果发现了一个很悲剧的事情,一万个数据里面,有几百个数据不完整,找了半天原因才发现,QByteArry在序列化过程中,首先序列化了自身的size,然后才是自身,导致序列化后大小比之前的size大了4,同样QString也是一样,就用一个自定义的结构体来做例子说明,首先自定义结构体

源码链接http://pan.baidu.com/s/1kVAAgTp

class sendStruct
{
public:
    explicit sendStruct(int Type,QString Description,QByteArray ByteData=QByteArray(0));
    int  Type;//用于区分发送的不同内容的数据,对应不同的解析方法
    QString Description;//发送内容的描述
    QByteArray ByteData;//具体发送或者接受的内容,可以将所有基本类型int,char,vector,map等或者自定义的结构体通过
                        //QDataStream序列化到ByteData中,接收端同样的方法从QDataStream中解析出来原数据
    sendStruct(){ Type=0; Description=""; ByteData=QByteArray(0);}
    int size()
        {
            int size=0;
            size=sizeof(int)+Description.size()*2+4+ByteData.size()+4;
            //序列化后QString大小为原有大小乘以2加4,QByteArry序列化后大小为原始大小加4,QString为Unicode编码每个字符占两个字节,
            //QString和QByteArry序列化过程中,首先序列化了本身大小的整形数据(qint32)到序列中,然后才是具体数据。
            return size;
        }
    int size() const
        {
            int size=0;
            size=sizeof(int)+Description.size()*2+4+ByteData.size()+4;
            return size;
        }
    sendStruct &operator=(const sendStruct &other)
        {
            Type=other.Type;
            Description=other.Description;
            ByteData=QByteArray(other.ByteData);
            return *this;
        }
#ifndef QT_NO_DATASTREAM
    friend QDataStream& operator <<(QDataStream& out,const sendStruct& senstruct)
        {
            out<<senstruct.Type
               <<senstruct.Description
               <<senstruct.ByteData;
            return out;
        }
    friend QDataStream& operator >>(QDataStream& in,sendStruct& senstruct)
        {
            in>>senstruct.Type
              >>senstruct.Description
              >>senstruct.ByteData;
            return in;
        }
#endif
};

定义TCP服务端和客户端

#ifndef TCPSERVERCONNECT_H
#define TCPSERVERCONNECT_H

#include <QObject>
#include<QTcpServer>
#include<QTcpSocket>
class sendStruct;
class TcpServerConnect : public QObject
{
    Q_OBJECT
public:
    explicit TcpServerConnect(QObject *parent = nullptr);
private:
    QTcpServer *m_server;
    QTcpSocket *m_tcpsocket;
    bool m_isGetPartData;
    int m_requestDataSize;
public slots:
    void handleSendOutData(const sendStruct&);
    void handleGetRecieveData();
    void handleNewConnection();
};

#endif // TCPSERVERCONNECT_H

#include "tcpserverconnect.h"

TcpServerConnect::TcpServerConnect(QObject *parent) : QObject(parent)
    {
        m_tcpsocket=nullptr;
        m_isGetPartData=false;
        m_requestDataSize=0;
        m_server=new QTcpServer(this);
        connect(m_server,&QTcpServer::newConnection,this,&TcpServerConnect::handleNewConnection);
        m_server->listen(QHostAddress::Any,6868);
    }

void TcpServerConnect::handleSendOutData(const sendStruct &data)
    {
        if((!m_tcpsocket)||m_tcpsocket->state()!=QAbstractSocket::ConnectedState)
            return;
        QDataStream out(m_tcpsocket);
        out<<data.size()<<data;//先发送了数据大小,在发送数据
        m_tcpsocket->flush();
        /*把需要发送的数据封装在结构体里面发送*/
    }

void TcpServerConnect::handleGetRecieveData()
    {
        if((!m_tcpsocket)||m_tcpsocket->state()!=QAbstractSocket::ConnectedState)
            return;
        if(m_isGetPartData==false){
                if(m_tcpsocket->bytesAvailable()<sizeof(int))//先要得到数据的大小
                    return;
                else
                    {
                        QDataStream in(m_tcpsocket);
                        in>>m_requestDataSize;//数据大小写入这个变量中
                        m_isGetPartData=true;//只获得了数据的大小,数据内容还未获得
                    }
            }
        if(m_isGetPartData==true){
                if(m_tcpsocket->bytesAvailable()<m_requestDataSize)//判断是否数据接收完整了,不完整就返回等待下一次判断
                    return;
                else
                    {
                        QDataStream in(m_tcpsocket);
                        sendStruct receiveData;
                        in>>receiveData;//接收到了发送端的数据
                        m_requestDataSize=0;//清空大小
                        m_isGetPartData=false;//清空标志
                        /*
                        数据接收成功,放置在receiveData中,可以做其他处理
                        doSomething(receiveData);
                        */
                        qDebug()<<"receiveData type"<<receiveData.Type;
                        qDebug()<<"receiveData Description"<<receiveData.Description;
                        qDebug()<<"receiveData ByteData"<<receiveData.ByteData;
                        if(m_tcpsocket->bytesAvailable())//如果缓存区还存在数据,继续执行
                            handleGetRecieveData();
                    }
            }
    }
void TcpServerConnect::handleNewConnection()
    {
        QTcpServer *server=static_cast<QTcpServer*>(sender());
        m_tcpsocket=server->nextPendingConnection();
        if(m_tcpsocket)
            connect(m_tcpsocket,&QTcpSocket::readyRead,this,&TcpServerConnect::handleGetRecieveData);
        
        sendStruct sendImageData;
        sendImageData.Type=0;
        sendImageData.Description=QString("this is image");
        QImage image(QSize(640,480),QImage::Format_RGB888);
        image.fill(Qt::gray);
        QBuffer buffur(sendImageData.ByteData);
        buffur.open(QIODevice::ReadWrite);
        image.save(&buffur,"JPG");
        handleSendOutData(sendImageData);
        
        sendStruct sendPointData;
        sendPointData.Type=1;
        sendPointData.Description="this is point";
        QDataStream pointStream(&sendPointData.ByteData,QIODevice::WriteOnly);
        pointStream<<QPoint(100,100);
        handleSendOutData(sendPointData);
        
    }



#ifndef TCPCLIENTCONNECT_H
#define TCPCLIENTCONNECT_H

#include <QObject>
#include<QTcpSocket>
class sendStruct;
class TcpClientConnect : public QObject
{
    Q_OBJECT
public:
    explicit TcpClientConnect(QObject *parent = nullptr);
    QTcpSocket *m_tcpsocket;
    bool m_isGetPartData;
    int m_requestDataSize;
public slots:
    void handleSendOutData(const sendStruct&);
    void handleGetRecieveData();
    void handleSocketConnected();
};

#endif // TCPCLIENTCONNECT_H

#include "tcpclientconnect.h"

TcpClientConnect::TcpClientConnect(QObject *parent) : QObject(parent)
    {
        m_tcpsocket=new QTcpSocket(this);
        m_isGetPartData=false;
        m_requestDataSize=0;
        connect(m_tcpsocket,&QTcpSocket::readyRead,this,&TcpClientConnect::handleGetRecieveData);
        connect(m_tcpsocket,&QTcpSocket::disconnected,this,&TcpClientConnect::handleSocketConnected);
        m_tcpsocket->connectToHost(QHostAddress("192.168.0.45"),6868);
        if(m_tcpsocket->waitForConnected(3000)==false){
                qDebug()<<"connect error:"<<m_tcpsocket->errorString();
            }
    }

void TcpClientConnect::handleSendOutData(const sendStruct &data)
    {
        if((!m_tcpsocket)||m_tcpsocket->state()!=QAbstractSocket::ConnectedState)
            return;
        QDataStream out(m_tcpsocket);
        out<<data.size()<<data;//先发送数据大小,在发送数据本身
        m_tcpsocket->flush();
        /*把需要发送的数据封装在结构体里面发送*/
    }

void TcpClientConnect::handleGetRecieveData()
    {
        if((!m_tcpsocket)||m_tcpsocket->state()!=QAbstractSocket::ConnectedState)
            return;
        if(m_isGetPartData==false){
                if(m_tcpsocket->bytesAvailable()<sizeof(int))//先接收数据的大小
                    return;
                else
                    {
                        QDataStream in(m_tcpsocket);
                        in>>m_requestDataSize;//数据大小写入变量
                        m_isGetPartData=true;//设置标志,只接收到了数据大小,没接收到数据全部
                    }
            }
        if(m_isGetPartData==true){
                if(m_tcpsocket->bytesAvailable()<m_requestDataSize)//判断是否接收到了完整的数据
                    return;
                else
                    {
                        QDataStream in(m_tcpsocket);
                        sendStruct receiveData;
                        in>>receiveData;//接收到了数据
                        m_requestDataSize=0;//清空大小
                        m_isGetPartData=false;//清空标志
                        /*
                        数据接收成功,放置在receiveData中,可以做其他处理
                        doSomething(receiveData);
                        */
                        qDebug()<<"receiveData type"<<receiveData.Type;
                        qDebug()<<"receiveData Description"<<receiveData.Description;
                        qDebug()<<"receiveData ByteData"<<receiveData.ByteData;
                        if(m_tcpsocket->bytesAvailable())//如果缓存区还存在数据,递归执行
                            handleGetRecieveData();
                    }
            }
    }

void TcpClientConnect::handleSocketConnected()
    {
        sendStruct sendImageData;
        sendImageData.Type=0;
        sendImageData.Description=QString("this is image");
        QImage image(QSize(640,480),QImage::Format_RGB888);
        image.fill(Qt::gray);
        QBuffer buffur(sendImageData.ByteData);
        buffur.open(QIODevice::ReadWrite);
        image.save(&buffur,"JPG");
        handleSendOutData(sendImageData);
        
        sendStruct sendPointData;
        sendPointData.Type=1;
        sendPointData.Description="this is point";
        QDataStream pointStream(&sendPointData.ByteData,QIODevice::WriteOnly);
        pointStream<<QPoint(100,100);
        handleSendOutData(sendPointData);
                
    }



版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/195771.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • goland2021.7.20激活码_在线激活

    (goland2021.7.20激活码)JetBrains旗下有多款编译器工具(如:IntelliJ、WebStorm、PyCharm等)在各编程领域几乎都占据了垄断地位。建立在开源IntelliJ平台之上,过去15年以来,JetBrains一直在不断发展和完善这个平台。这个平台可以针对您的开发工作流进行微调并且能够提供…

    2022年3月21日
    43
  • 机器学习 之 Haar特征

    机器学习 之 Haar特征Haar特征Haar特征原理综述Haar特征是一种反映图像的灰度变化的,像素分模块求差值的一种特征。它分为三类:边缘特征、线性特征、中心特征和对角线特征。用黑白两种矩形框组合成特征模板,在特征模板内用黑色矩形像素和减去白色矩形像素和来表示这个模版的特征值。例如:脸部的一些特征能由矩形模块差值特征简单的描述,如:眼睛要比脸颊颜色要深,鼻梁两侧比鼻梁颜色要深,嘴巴比周围颜色要深等。但矩形特征只对一

    2022年6月16日
    41
  • PKI体系标准_三体系

    PKI体系标准_三体系转自CSDN.在PKI体系中涉及到四类标准,下面做个简单介绍。1.asn.1基本编码规范Asn.1是描述在网络上传输信息格式的标准方法。它有两个部分:第一部分(X.208)描述信息内的数据、数据类型及序列格式,也就是数据的语法;第二部分(X.209)描述如何将各部分数据组成消息,也就是数据的基本编码规则(DER编码)。Asn.1原来是作为X.409的一部分而开发的,后来独立发展

    2022年8月22日
    8
  • 微信小程序—-全局变量「建议收藏」

    微信小程序—-全局变量「建议收藏」方法二:用引入js的方法定义全局变量实例:我在公用文件夹src下的js文件夹中创建的三个保存全局变量的文件:base64.js、config.js、data.js这三个文件作用:示例代码:使用方法:方法三:使用全局状态管理库微信小程序—-全局状态管理(便于全局埋点等操作)微信小程序—-redux在原生微信小程序的使用实例我的博客,欢迎交流!我的CSDN博客,欢迎交流!微信小程序专栏前端笔记专栏微信小程序实现部分高德地图功能的DEMO下载微信小…

    2022年9月27日
    2
  • 国内可用的ntp服务器地址

    国内可用的ntp服务器地址ntp.sjtu.edu.cn202.120.2.101(上海交通大学网络中心NTP服务器地址)s1a.time.edu.cn 北京邮电大学s1b.time.edu.cn 清华大学s1c.time.edu.cn 北京大学s1d.time.edu.cn 东南大学s1e.time.edu.cn 清华大学s2a.time.edu.cn 清华大学s2b.time.edu.c

    2022年6月6日
    85
  • hostapd 移植和使用[通俗易懂]

    hostapd 移植和使用[通俗易懂]一、hostapd简介hostapd是一个用户态用于AP和认证服务器的守护进程。它实现了IEEE802.11相关的接入管理,IEEE802.1X/WPA/WPA2/EAP认证,RADIUS客户端,EAP服务器和RADIUS认证服务器。二、hostapd移植1.打开hostap官网,下载hostapd-2.7.tar.gz源码包;      2.解压源码包:…

    2022年5月22日
    40

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号