zoukankan      html  css  js  c++  java
  • 客户端服务端通信protocol

    这个协议不知我在上面耗费了多长时间,也有人问过我咋回事,这个protocol不长,但对于我来说理解起来很费劲,今天回来看看忽然看懂了(80%),只能说不知看了多少遍

    其实这些东西应该在来的一个月这样子都要会的,一直拖到现在,其实那时时真心看不懂

    #ifndef Protocol_Base_H
    #define Protocol_Base_H
    
    //#include <boost/cstdint.hpp>
    #include <string.h>
    #pragma pack(push, 1)
    //-----------基础协议--------------
    struct Protocol
    {
        unsigned char    cmd_type;
        int                size;//content的长度, 不包含本协议头
        void*            content;//内容的地址
    
        int to_buffer(void* buffer, int buffer_len)
        {
            if(!buffer)
                return -1;
            //-sizeof(void*)其实这个content没多大作用其实就是标示了一个位置,发送的时候需要将其减去,因为后面直接将内容复制到了这个指针的位置
            int total_size = size + sizeof(Protocol) - sizeof(void*);
            if(buffer_len < total_size)
                return -1;
    
            Protocol* p = (Protocol*)buffer;
            p->cmd_type = this->cmd_type;
            p->size = this->size;
            if (content)
            {
                //这句让我理解这个协议费劲了苦头,今天在看终于懂了,也许对c++基础好点的一下就能看懂,我不知看了多少次
                //原来看实在不理解这个&p->content,为什么指针还是要取地址,一直在想是指针了还取指针干什么,一直在钻
                //其实Protocol* p = (Protocol*)buffer;这个转换可以看下content的值是0,buffer里面存放了指针,然后取指针的地址
                //也就是buffer里面这个指针的地址,memcpy将内容复制到指针地址的位置,正好在buffer里面
                //包结构(1字节:cmd_type)(4字节:size表示内容的长度)(要发送的内容)
                memcpy(&p->content, content, size);
            }
            return total_size;
        }
    
        bool from_buffer(void* buffer, int len)
        {        
            if(!buffer)
                return false;
            int head_size = sizeof(Protocol) - sizeof(void*);
            if(len < head_size)//代表空数据
                return false;
    
            Protocol* p = (Protocol*)buffer;
            //*this = *p; 长度为5的情况下会出错
            this->cmd_type = p->cmd_type;
            this->size = p->size;
            if(size)
            {
                if(len < head_size + (int)size)
                {
                    return false;
                }
                //这个有点难理解,buffer里面是没有content内容的,个人感觉可以将content理解成一个位置,然后去这个位置的地址,正好是内容的地址
                content = &p->content;
            }
            return true;
        }
    };
    
    #pragma pack(pop)
    
    #endif //Protocol_Base_H
    
    
    #include <iostream>
    #include <vector>
    #include "protocol.h"
    using namespace std;
    //模拟放松命令是1,发送一个int 100
    //发送的时候需要分配一个buffer,然后发送这个buffer,接收的时候需要分配一个buffer,然后从这个buffer里面解析
    void* g_data = new char[100];
    int g_len;
    void send()
    {
        void* data = new int;
        *(int*)data = 100;//数据
        int len = 4;    //长度
        int cmd = 1;    //命令
        vector<char> buffer;
        buffer.resize(len + sizeof(Protocol));
    
        Protocol pt = {0};
        pt.cmd_type = cmd;
        pt.content = data;
        pt.size = len;
        g_len = pt.to_buffer(&buffer[0], buffer.size());//注意不要&buffer因为buffer是对象在栈上的地址
        memcpy(g_data, &buffer[0], g_len);//复制到这个全局的里面方便
    
    }
    
    void recv()
    {
        Protocol pt = {0};
        pt.from_buffer(g_data, g_len);
        cout << *(int*)pt.content;//这样就可以按照协议发送各种结构体形式的了,这边解析之后强转一下就行了
    }
    
    int main()
    {
        send();
        recv();
        getchar();
        return 0;
    }
  • 相关阅读:
    Wix 教程
    SQL插入數據變成?解決辦法
    DevExpress GridControl使用方法总结【轉】
    Javascript如何判断对象是否相等【轉】
    android StringBuffer类的使用
    Linux命令
    PHP解决中文乱码
    PHP防盗链技术
    0113进度条+ListView+ArrayList+Adapter用法
    Windows中32位(x86)和64位(x64)解释
  • 原文地址:https://www.cnblogs.com/zzyoucan/p/3978375.html
Copyright © 2011-2022 走看看