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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • C++中this指针的作用以及用法详解

    C++中this指针的作用以及用法详解为什么引用this指针?当我们在类中定义了一个变量,同时又在类成员函数中定义了同一个变量时,也就是变量名重复时,但是我们要想使用类中的定义的变量,此时就需要this指针了。1.this指针的作用指针存在于类的成员函数中,指向被调用函数类实例的地址。 一个对象的this指针并不是对象本身的一部分,不会影响sizeof()的结果。this指针的作用域是在类内部,当在类的非静态成员函

    2022年5月13日
    43
  • 设备树传参中的platform device的匹配

    设备树传参中的platform device的匹配在高版本的Linux内核中使用了设备树进行传参,之前购买一块nanopi的板子使用的是linux4.11.2版本的内核(使用的友善之臂的Mainlinelinux)就是这种情况,并且使用设备树传参过后,原来硬编码在mach-xxx.c文件中的platformdevice全部都放入了设备树中,而原来使用name进行platformdevice和driver进行匹配的方式也发生了变化。以

    2022年7月24日
    13
  • Mit6.S081-实验1-Xv6 and Unix utilities

    Mit6.S081-实验1-Xv6 and Unix utilitiesMit6.S081-实验1-Xv6andUnixutilities前言一、Bootxv61,实验目的2,操作流程1)切换到xv6-labs-2020代码库的lab1分支2)启动xv63)测试xv64)过程分析5)其他操作二、在xv6中添加一个自己编写的程序1,源码准备2,编译配置3,测试添加程序4,过程分析三、xv6中shell简析前言一、Bootxv61,实验目的利用qemu启动xv62,操作流程1)切换到xv6-labs-2020代码库的lab1分支gitcheckoutut

    2022年9月26日
    0
  • SpringCloud架构图及简介[通俗易懂]

    SpringCloud架构图及简介[通俗易懂]SpringCloud架构图SpringCloud介绍微服务开发模式2014年说的微服务服务,号称兼顾Dev(开发)和Ops(运维),但实际大多数人都在讲Dev,包括框架SpringBoot/SpringCloud,方法论DDD,包括容器化Docker,强调都是开发2016年CNCF大力推广云原生(CloudNative)概念,推出K8S等运维平台或工具,才逐渐偏向运维Springboot:搭建微服务的基石,可以帮我们快速、方便的启动一个微服务应用Spring

    2022年5月27日
    206
  • java中的变量各占得字节数

    java中的变量各占得字节数java中的变量各占得字节数

    2022年4月23日
    43
  • CANalyzer及CANOE使用五:无DBC,调CSV方式的网关信号转发或单通道信号值控制ECU其他信号变化(包含设计自动化测试)[通俗易懂]

    CANalyzer及CANOE使用五:无DBC,调CSV方式的网关信号转发或单通道信号值控制ECU其他信号变化(包含设计自动化测试)[通俗易懂]前言Panel界面CSV文件解析发送与接收————————————————前言同事:CAN网络UDS、NM等可以实现自动化,功能信号是否也可以?有简单方法吗?手动测太累了,矩阵表信号那么多,几十个Bit都够算了,脑袋都昏了。我:可以哇,那就整一个自动算信号bit值的吧。同事:不仅要算,还要判断ECU接收某些开关信号、温度、档位等的一系列反应(其他信号值的改变是否正确)我:可以,整一个同事:还有可能有网关转发信号起始bit,bit长度,接收的一方的信号值也要变。我:。。。。。。Pa.

    2022年6月20日
    32

发表回复

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

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