码迷,mamicode.com
首页 > 其他好文 > 详细

封装一个带大小的封包,防止Tcp粘包、拆包

时间:2020-02-16 16:37:35      阅读:84      评论:0      收藏:0      [点我收藏+]

标签:长度   new t   soc   typedef   name   null   instance   har   pack   

C++

头文件

#ifndef TCPWRAP_H
#define TCPWRAP_H

#include <memory>
#include <netinet/in.h>
#include <string.h>

#pragma pack(push,1)

typedef struct
{
    size_t length;  //包头(包体长度)
    char* body; //包体
}Packet;

#pragma pack(pop)

class TcpDataWrap
{
private:
    static TcpDataWrap* m_instance;
    TcpDataWrap();

public:
    static TcpDataWrap* instance();

    void sendPackData(int sockfd,char* data,int nLen);

    std::shared_ptr<char> recvUnpackData (int sockfd);
    
};

#endif

源文件

#include "tcpwrap.h"
#include <iostream>
using namespace std;

TcpDataWrap* TcpDataWrap::m_instance = NULL;

TcpDataWrap* TcpDataWrap::instance()
{
    if(m_instance == NULL)
    {
        m_instance = new TcpDataWrap();
    }
    return m_instance;
}

TcpDataWrap::TcpDataWrap() {}


void TcpDataWrap::sendPackData(int sockfd,char* data,int nLen)
{
    Packet p;
    size_t headSize = sizeof(size_t);
    p.length = nLen;
    
    size_t totalLen = headSize + nLen;

    char* buf = new char[totalLen];
    memcpy(buf, &p.length, headSize);
    memcpy(buf + headSize, data, nLen);
    send(sockfd, buf, totalLen,0);
}

//返回一个指向char*的智能指针
std::shared_ptr<char> TcpDataWrap::recvUnpackData (int sockfd)
{
    size_t byteRead=0;
    size_t bodyLen = 0;
    while (byteRead <sizeof(size_t))
    {
        byteRead = recv(sockfd, &bodyLen, sizeof(size_t), MSG_PEEK);    //查看数据长度是否满足头文件的要求
    }
    recv(sockfd, &bodyLen, sizeof(size_t), 0);

    char* data = new char[bodyLen];
    char* pData = data;
    
    size_t byteLeft = bodyLen;

    while (byteLeft>0)
    {
        byteRead = recv(sockfd, data, byteLeft, 0);
        byteLeft -= byteRead;
        pData += byteRead;
    }
    std::shared_ptr<char> ret(data);
    return ret;
}

QT

头文件

#ifndef TCPWRAP_H
#define TCPWRAP_H

#include <memory>
#include <string.h>
#include <QTcpSocket>

#pragma pack(push,1)


typedef struct
{
    size_t length;  //包头(包体长度)
    char* body; //包体
}Packet;

#pragma pack(pop)


class TcpDataWrap : public QObject
{
public:
    static TcpDataWrap* instance();
    void sendPackData(QTcpSocket* sockfd, char* data, int nLen);
    std::shared_ptr<char> recvUnpackData (QTcpSocket* sockfd);

private:
    TcpDataWrap();
    static TcpDataWrap* m_instance;
};

#endif // TCPWRAP_H

源文件

#include "tcpwrap.h"
#include <QTcpSocket>

TcpDataWrap* TcpDataWrap::m_instance = nullptr;

TcpDataWrap* TcpDataWrap::instance()
{
    if(m_instance == nullptr)
    {
        m_instance = new TcpDataWrap();
    }
    return  m_instance;
}

TcpDataWrap::TcpDataWrap(){}

void TcpDataWrap::sendPackData(QTcpSocket* sockfd, char* data, int nLen)
{
    Packet p;
    size_t headSize = sizeof(size_t);
    p.length = nLen;
    size_t totalLen = headSize+nLen;
    char* buf = new char[totalLen];
    memset(buf,0,totalLen);
    memcpy(buf,&p.length,headSize);
    memcpy(buf+headSize,data,nLen);
    sockfd->write(buf,totalLen);
}

std::shared_ptr<char> TcpDataWrap::recvUnpackData (QTcpSocket* sockfd)
{
    size_t byteRead = 0;
    size_t bodyLen;
    while (byteRead<sizeof (size_t))
    {
        byteRead=sockfd->bytesAvailable();
    }

    sockfd->read((char*)&bodyLen,sizeof (size_t));
    char* data = new char[bodyLen];
    char* pData = data;
    size_t byteLeft = bodyLen;
    while (byteLeft>0)
    {
        byteRead=sockfd->read(data,byteLeft);
        byteLeft -= byteRead;
        pData += byteRead;
    }

    std::shared_ptr<char> ret(data);
    return  ret;
}

封装一个带大小的封包,防止Tcp粘包、拆包

标签:长度   new t   soc   typedef   name   null   instance   har   pack   

原文地址:https://www.cnblogs.com/WindSun/p/12317108.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!