封装IWeb其实并不算是GUI的范畴,但是一并说了罢。在BREW中实现网络访问有两个选择:ISocket和IWeb,我是比较倾向于使用IWeb的,只要你不是要做一个长连接。因为服务端程序比较容易做,可以直接使用现成的WEB服务器,我们不再需要自己处理并发、缓存等网络服务必须要考虑的东西。

使用IWeb并非只能处理HTML的页面,事实上我们完全可以拿它来做文件下载、提交信息(如下载报告)之类的管理。也并非IWeb只能与IHtmlViewer合并使用,我们完全可以将一个IMenuCtl的信息打成二进制包使用IWeb下载并用IMenuCtl来展示,也就是说把它当成一个ISocket一样来使用。

首先我们需要定义一个回调,用WSNotify定义了回调的通知参数,包括状态、代码以及获取的内容等等。

typedef struct _IWebSocket IWebSocket;

//定义回调的参数
typedef struct
...{
    uint16  wStatus;
    int        wCode;
    byte    *pBuffer;
    uint32    bLength;
    uint32    cLength;

} WSNotify;

//定义回调格式
typedef void (*PFNWSOCKETNOTIFY)(
      void *            pvUser,
      WSNotify            aWSNotify
   );

再看看这个组件包括的成员变量有哪些吧,除了IWeb和IWebResp以外,还需要回调cbNotify、目标地址m_TargetURL、临时的内容缓冲区m_BodyBuffer等成员:

struct _IWebSocket
...{
    const AEEVTBL(IWebSocket) * pvt;

    uint32          m_nRefs;    
    IShell            *m_pIShell;
    IModule            *m_pIModule;

    AEECallback    cb; 

    PFNWSOCKETNOTIFY    cbNotify;
    void                *pUser;
    
    IWeb        *m_pIWeb;    
    IWebResp    *m_piWResp; 
    
    //保存下载文件内容的缓冲区
    byte        *m_BodyBuffer;    
    uint32        m_BodySize;    
    uint32        m_BodyAllocSize;

    char        *m_LocationURL;

    //目标URL
    char        *m_TargetURL;
    char        *m_Header;

    //当前状态
    uint8        m_State;

    //尝试次数
    uint8        tryCount;

    byte        buf[1024];
    byte        cBuffer[10240];
    int            cLen;

};

要实现的接口函数是:

AEEINTERFACE(IWebSocket)
...{
    DECLARE_IBASE(IWebSocket)    

    byte*        (*GetBuffer)            (IWebSocket * po,uint32 * outSize);
    void        (*SetNotifyFn)            (IWebSocket * po,PFNWSOCKETNOTIFY cb,void * pUser);
    void        (*SetHeader)            (IWebSocket * po,const char * header);
    void        (*SetURL)                (IWebSocket * po,const char * url);
    void        (*Stop)                    (IWebSocket * po);
    void        (*Resume)                (IWebSocket * po);
    void        (*Start)                (IWebSocket * po);    
    void        (*StartStream)            (IWebSocket * po);
    
};

OK,实现就类似于BREW中的那个 IWeb例子,做两个Start函数,一个是普通的下载(每下一个包回调一次),另一个是流式(建立一个小的缓冲区,这个小缓冲满了则回调一次):

static void IWebSocket_Start(IWebSocket *pMe)
...{
    FREEIF(pMe->m_BodyBuffer);
    pMe->m_BodyBuffer = NULL;
    pMe->m_BodySize = 0;
    pMe->m_BodyAllocSize = 0;

    CALLBACK_Cancel(&pMe->cb);
    CALLBACK_Init(&pMe->cb, webDownloadData, pMe);
    
    if(!pMe->m_pIWeb)
        initWeb(pMe);

    IWEB_GetResponse(pMe->m_pIWeb,
                        (pMe->m_pIWeb, &pMe->m_piWResp, &pMe->cb, pMe->m_TargetURL, 
                        WEBOPT_HANDLERDATA, pMe, 
                        WEBOPT_HEADERHANDLER, webHeader, 
                        WEBOPT_STATUSHANDLER, webStatus, 
                        WEBOPT_END));
  
}
static void IWebSocket_StartStream(IWebSocket *pMe)
...{
    FREEIF(pMe->m_BodyBuffer);
    pMe->m_BodyBuffer = NULL;
    pMe->m_BodySize = 0;
    pMe->m_BodyAllocSize = 0;

    pMe->cLen=0;
    MEMSET(pMe->buf,0,sizeof(pMe->buf));
    MEMSET(pMe->cBuffer,0,sizeof(pMe->cBuffer));

    CALLBACK_Cancel(&pMe->cb);
    CALLBACK_Init(&pMe->cb, webDownloadStream, pMe);
    
    if(!pMe->m_pIWeb)
        initWeb(pMe);

    IWEB_GetResponse(pMe->m_pIWeb,
                        (pMe->m_pIWeb, &pMe->m_piWResp, &pMe->cb, pMe->m_TargetURL, 
                        WEBOPT_HANDLERDATA, pMe, 
                        WEBOPT_HEADERHANDLER, webHeader, 
                        WEBOPT_STATUSHANDLER, webStatus, 
                        WEBOPT_END));
  
}

两个下载的具体实现是:

//响应
static void webDownloadData(void * p)
...{
    IWebSocket *pMe = (IWebSocket *)p;
    
    WebRespInfo *pwri;
    int ByteCount;
           
    pwri = IWEBRESP_GetInfo(pMe->m_piWResp);

    if( !WEB_ERROR_SUCCEEDED(pwri->nCode) )
    ...{
        FREEIF(pMe->m_BodyBuffer);
        pMe->m_BodyBuffer = NULL;
        pMe->m_BodySize = 0;
        pMe->m_BodyAllocSize = 0;

        if( (pwri->nCode==302 || pwri->nCode==301) && pMe->m_LocationURL!=NULL )
        ...{
            pMe->tryCount=0;

            FREEIF(pMe->m_TargetURL);
            pMe->m_TargetURL=NULL;
            pMe->m_TargetURL=STRDUP(pMe->m_LocationURL);

            FREEIF(pMe->m_LocationURL);
            pMe->m_LocationURL=NULL;
            
            IWebSocket_Stop(pMe);
            ISHELL_SetTimer(pMe->m_pIShell,0,(PFNNOTIFY)IWebSocket_Start,(void*)pMe);
            return;
        }

        if(pMe->tryCount<MAX_TRY_COUNT)
        ...{
            IWebSocket_Stop(pMe);
            pMe->tryCount++;
            ISHELL_SetTimer(pMe->m_pIShell,3000,(PFNNOTIFY)IWebSocket_Start,(void*)pMe);
        }
        else
        ...{
            WSNotify wsn;
            wsn.wCode=pwri->nCode;
            wsn.wStatus=WS_STATUS_ERROR;
            wsn.pBuffer=NULL;
            wsn.bLength=0;
            wsn.cLength=0;
            pMe->cbNotify(pMe->pUser,wsn);
        }
        return;
    }
    ISHELL_CancelTimer(pMe->m_pIShell,(PFNNOTIFY)IWebSocket_Start,(void*)pMe);

    MEMSET(pMe->buf,0,sizeof(pMe->buf));       
    if ((ISource *)0 != pwri->pisMessage) 
    ...{
        ISource * pISource = pwri->pisMessage;
        ByteCount =    ISOURCE_Read(pISource, (char *)pMe->buf, sizeof(pMe->buf));
        
        switch(ByteCount)
        ...{
            case ISOURCE_END:    //表示读网络完成                        
                ...{
                    WSNotify wsn;

                    IWebSocket_Stop(pMe);
                    
                    wsn.wCode = 0;
                    wsn.wStatus = WS_STATUS_SUCCESS;
                    wsn.pBuffer=pMe->m_BodyBuffer;
                    wsn.bLength=pMe->m_BodySize;
                    wsn.cLength=pwri->lContentLength;

                    pMe->cbNotify(pMe->pUser,wsn);                
                    break;
                }
           case ISOURCE_ERROR:
                ...{
                    WSNotify wsn;
                    wsn.wCode=pwri->nCode;
                    wsn.wStatus=WS_STATUS_ERROR;
                    wsn.pBuffer=NULL;
                    wsn.bLength=0;
                    wsn.cLength=pwri->lContentLength;

                    pMe->cbNotify(pMe->pUser,wsn);
                }
                break;
           case ISOURCE_WAIT:               
                ISOURCE_Readable(pISource, &pMe->cb);
                break;
           default:               
               if (ByteCount)
               ...{
                    if (pMe->m_BodySize + ByteCount > pMe->m_BodyAllocSize)
                    ...{
                        const int NewSize = pMe->m_BodyAllocSize + ByteCount;
                        byte* NewBuf = (byte*)REALLOC(pMe->m_BodyBuffer, NewSize);
                       
                        if (NewBuf)
                        ...{
                            pMe->m_BodyBuffer = NewBuf;
                            pMe->m_BodyAllocSize = NewSize;
                        }
                        else
                            return;
                    }
                    if(pMe->m_BodySize + ByteCount <= pMe->m_BodyAllocSize)
                    ...{
                        MEMCPY(pMe->m_BodyBuffer + pMe->m_BodySize, pMe->buf, ByteCount);
                        pMe->m_BodySize += ByteCount;
                    }

                    //每次下一个包,则回调一次
                    ...{
                        WSNotify wsn;
                        wsn.wCode = pwri->nCode;
                        wsn.wStatus = WS_STATUS_TICK;
                        wsn.pBuffer=pMe->m_BodyBuffer;
                        wsn.bLength=pMe->m_BodySize;
                        wsn.cLength=pwri->lContentLength;

                        pMe->cbNotify(pMe->pUser,wsn);    
                    }
               }
               
               ISOURCE_Readable(pISource, &pMe->cb);
               break;
           } 
       }        
}

和流式:

//流式响应
static void webDownloadStream(void * p)
...{
    IWebSocket *pMe = (IWebSocket *)p;
    
    WebRespInfo *pwri;
    int ByteCount;
           
    pwri = IWEBRESP_GetInfo(pMe->m_piWResp);

    if( !WEB_ERROR_SUCCEEDED(pwri->nCode) )
    ...{
        FREEIF(pMe->m_BodyBuffer);
        pMe->m_BodyBuffer = NULL;
        pMe->m_BodySize = 0;
        pMe->m_BodyAllocSize = 0;

        if( (pwri->nCode==302 || pwri->nCode==301) && pMe->m_LocationURL!=NULL )
        ...{
            pMe->tryCount=0;

            FREEIF(pMe->m_TargetURL);
            pMe->m_TargetURL=NULL;
            pMe->m_TargetURL=STRDUP(pMe->m_LocationURL);

            FREEIF(pMe->m_LocationURL);
            pMe->m_LocationURL=NULL;
            
            IWebSocket_Stop(pMe);
            ISHELL_SetTimer(pMe->m_pIShell,0,(PFNNOTIFY)IWebSocket_StartStream,(void*)pMe);
            return;
        }

        if(pMe->tryCount<MAX_TRY_COUNT)
        ...{
            IWebSocket_Stop(pMe);
            pMe->tryCount++;
            ISHELL_SetTimer(pMe->m_pIShell,3000,(PFNNOTIFY)IWebSocket_StartStream,(void*)pMe);
        }
        else
        ...{
            WSNotify wsn;
            wsn.wCode=pwri->nCode;
            wsn.wStatus=WS_STATUS_ERROR;
            wsn.pBuffer=NULL;
            wsn.cLength=0;
            wsn.bLength=0;
            pMe->cbNotify(pMe->pUser,wsn);
        }
        return;
    }
    ISHELL_CancelTimer(pMe->m_pIShell,(PFNNOTIFY)IWebSocket_StartStream,(void*)pMe);
    
    MEMSET(pMe->buf,(byte)'',sizeof(pMe->buf));       
    if ((ISource *)0 != pwri->pisMessage) 
    ...{
        ISource * pISource = pwri->pisMessage;
        ByteCount =    ISOURCE_Read(pISource, (char *)pMe->buf, sizeof(pMe->buf));
        
        switch(ByteCount)
        ...{
            case ISOURCE_END:    //表示读网络完成                        
                ...{
                    WSNotify wsn;

                    IWebSocket_Stop(pMe);

                    //先回调一次tick
                    wsn.wCode=pwri->nCode;
                    wsn.wStatus=WS_STATUS_TICK;
                    wsn.pBuffer=pMe->cBuffer;
                    wsn.bLength=pMe->cLen;
                    wsn.cLength=pwri->lContentLength;

                    pMe->cbNotify(pMe->pUser,wsn);
                    
                    //再回调成功
                    
                    wsn.wCode = 0;
                    wsn.wStatus = WS_STATUS_SUCCESS;
                    wsn.pBuffer=NULL;
                    wsn.bLength=0;
                    wsn.cLength=pwri->lContentLength;

                    pMe->cbNotify(pMe->pUser,wsn);
                
                    break;
                }
           case ISOURCE_ERROR:
                ...{
                    WSNotify wsn;
                    wsn.wCode=pwri->nCode;
                    wsn.wStatus=WS_STATUS_ERROR;
                    wsn.pBuffer=NULL;
                    wsn.bLength=0;
                    wsn.cLength=pwri->lContentLength;

                    pMe->cbNotify(pMe->pUser,wsn);
                }
                break;
           case ISOURCE_WAIT:               
                ISOURCE_Readable(pISource, &pMe->cb);
                break;
           default:               
               if (ByteCount)
               ...{
                    if(pMe->cLen + ByteCount <= sizeof(pMe->cBuffer))
                    ...{
                        //如果可以先放入临时空间
                        MEMCPY(pMe->cBuffer + pMe->cLen, pMe->buf, ByteCount);
                        pMe->cLen += ByteCount;
                    }
                    else
                    ...{
                        //临时空间如果满了,则回调一次
                        WSNotify wsn;
                        wsn.wCode=pwri->nCode;
                        wsn.wStatus=WS_STATUS_TICK;
                        wsn.pBuffer=pMe->cBuffer;
                        wsn.bLength=pMe->cLen;
                        wsn.cLength=pwri->lContentLength;

                        pMe->cbNotify(pMe->pUser,wsn);

                        //然后将当前的内容再放入临时空间,从头开始了
                        MEMCPY(pMe->cBuffer,pMe->buf,ByteCount);
                        pMe->cLen=ByteCount;
                    }
                    
               }
               
               ISOURCE_Readable(pISource, &pMe->cb);
               break;
           } 
       }    
}

OK。就是这样了,可以在回调中使用那个pBuffer,也可以在最后用GetBuffer取结果。

在BREW中打造自己的GUI(8)-IWEB的封装相关推荐

  1. ucgui在windows上的移植,及为go语言打造简易跨平台GUI的想法

    go语言缺乏官方GUI的支持,这点有时候很不方便. 虽然网上有很多开源的实现,但都不太满意,不太好用. 网上开源的有哪些?参见<2019,Go GUI项目爆发的一年?>https://st ...

  2. python tkinter库、添加gui界面_使用Python中tkinter库简单gui界面制作及打包成exe的操作方法(二)...

    使用Python中tkinter库简单gui界面制作及打包成exe的操作方法(二),创建一个,界面,布局,文件,路径 使用Python中tkinter库简单gui界面制作及打包成exe的操作方法(二) ...

  3. 【推荐】BREW中 - 显示和图像

    a. BREW 支持哪些图像格式? 适用版本: 1.0, 1.1, 2.0 BREW 支持颜色深度达到运行设备上提供的值的任何 BMP 文件. BREW 目前尚不支持 GIF 和 JPEG 图像. 有 ...

  4. python 面部识别_一文教你在Python中打造你自己专属的面部识别系统

    原标题:一文教你在Python中打造你自己专属的面部识别系统 人脸识别是用户身份验证的最新趋势.苹果推出的新一代iPhone X使用面部识别技术来验证用户身份.百度也在使"刷脸"的 ...

  5. java中把gui插入图片_在java中使用图片实现gui的美化.pdf

    在java中使用图片实现gui的美化.pdf 还剩 3页未读, 继续阅读 下载文档到电脑,马上远离加班熬夜! 亲,喜欢就下载吧,价低环保! 内容要点: 图形图像处理GRAPHICS AND IMAGE ...

  6. 将Simulink中的数据更新到GUI中(记录)

    1.前记:实时更新Simulink的数据并在GUI中显示出来,属于GUI与Simulink中的数据交换问题. 多次搜索还是在MATLAB answers中找到了一种解决方式. 来源:https://w ...

  7. Git中文化 ,Git GUI Here汉化

    Git怎么中文化?Git GUI Here Git安装的是英文,是下面的状态: 改成中文的,这时候就需要一个小小的文件:zh_cn.msg 已上传,下载地址(https://download.csdn ...

  8. 在WPSOffice中打造自己的素材库(转)

    在WPSOffice中打造自己的素材库(转) 最近安装了WPS Office 2002,发现软件中增加了"符号库"和"素材库",这对我们老师来说,实用性大大增强 ...

  9. java两个gui_Java中,图形用户界面简称GUI,它的组件包含在 java.awt 和______这两个包中。_学小易找答案...

    [单选题]( )是一种通过真实的生活事件和生活情境,培养幼儿的基本社会生活能力和技能,并增进幼儿的相关知识,激发幼儿的社会情感的方法. [单选题]假设翻译时可从任一核苷酸起始读码,人工合成的(AAC) ...

  10. 如何在微信中打造一个社区?粉丝君说案例

    又到了年中总结,这一年的运营工作也快收尾,那就借着这个话题总结下这一年我在运营上的突破吧. 除了继续打理公众号及头条号外,今年我又增加了一个微信社区--粉丝圈.这个产品不得了啊,不得了.好的产品运营起 ...

最新文章

  1. 使用Typescript重写axios
  2. Visual studio 利用Nuget 控制台安装已经下载好的插件
  3. 如何创建字符串(OC)
  4. 做产品:光有换位思考还不够
  5. Excel 数据导入到Access数据库,报错“找不到可安装的ISAM”的解决办法
  6. 使用HTTPS方式向git托管网站推送项目时输错用户名密码
  7. fastjson 序列化 不包括转义字符_fastjson再次发现漏洞,可能发生OOM导致宕机
  8. 开课吧:Html5有哪些新特性?
  9. python 加减法 负数_python解决两位数加减法快速出题问题
  10. iso硬盘安装 凤凰os_phoenix os安装全教程 凤凰系统进不去安装注意事项
  11. Android之画图
  12. 这几天心里颇不宁静,采的不是信号,而是寂寞
  13. 2022.3.2复盘
  14. 论坛报名 | 群体智能
  15. Android 开发高手课 课后练习(1 ~ 5)
  16. 地图标绘软件_如何制作专题地图(设计、规划、测绘制作图斑)标绘使用详解...
  17. 为什么浏览器请求一个接口有两次其中一次是Request Method: OPTIONS
  18. ssm保险办理系统毕业设计源码012232
  19. 格式塔理论/Gestalt theory
  20. 网上超市系统参考网站

热门文章

  1. matlab从mp4文件中提取音频,如何提取mp4视频中的音频文件 将视频转换为MP3音频...
  2. Field II 超声声场仿真(2): 接收灵敏度(原理代码)
  3. 对 sass和less的理解
  4. 极简IEEE文献数据库入门
  5. EXP6 信息搜集与漏洞扫描 20154328 常城
  6. 计算机系统中引入虚拟内存的好处是什么,虚拟内存的作用是什么
  7. 【用友CTO】解读企业数字化中台
  8. Log4j2-Log4j 2介绍及使用
  9. 高通开发-烧写及异常启动分析
  10. mapboxgl 纠偏百度地图