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);
                
    }

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 1.注册或登录页面设计:UILabel,UIButton,UITextField

    1.注册或登录页面设计:UILabel,UIButton,UITextField

  • 修改apache服务器端口号_apache修改端口号

    修改apache服务器端口号_apache修改端口号一、修改/etc/httpd/conf/httpd.conf文件中的监听端口号Listen80把80修改成需要的号,如8000,即Listen8000二、查看SELinux下http相关端口#semanageport-l|grephttphttp_cache_port_ttcp3128,8080,8118,10001-10010http_cache_po

  • Pytest(17)运行未提交的git(pytest-picked)

    Pytest(17)运行未提交的git(pytest-picked)前言我们每天写完自动化用例后都会提交到git仓库,随着用例的增多,为了保证仓库代码的干净,当有用例新增的时候,我们希望只运行新增的未提交git仓库的用例。pytest-picked插件可以

  • android调用相册和摄像头_js调用手机截屏保存到相册

    android调用相册和摄像头_js调用手机截屏保存到相册Android调用系统的拍照,打开相册功能1添加权限:uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>uses-permissionandroid:name="android.permission.CAMERA"/>2设置标志(回传码)//

  • ubuntu 局域网传输文件

    ubuntu 局域网传输文件scp[可选参数]file_sourcefile_target参数说明:-1:强制scp命令使用协议ssh1 -2:强制scp命令使用协议ssh2 -4:强制scp命令只使用IPv4寻址 -6:强制scp命令只使用IPv6寻址 -B:使用批处理模式(传输过程中不询问传输口令或短语) -C:允许压缩。(将-C标志传递给ssh,从而打开压缩功能) -p:保留原文件的修改时间,访问时间和访问权限。 -q:不显示传输进度条。 -r:递归复制整个目录。 -v:详细方.

  • $random 函数用法「建议收藏」

    $random 函数用法「建议收藏」$random函数调用时,返回一个32位的随机数,它是一个带符号的整形数。如下例:reg[23:0]rand;rand=$random%60;//产生一个在-59~59范围的随机数reg[23:0]rand;rand={$random}%60;//通过位拼接操作{}产生0~59范围的随机数产生一个在min,max之间随机数的例子:reg[23:…

发表回复

您的电子邮箱地址不会被公开。

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