2、动态库的使用和升级为框架

1、动态库的使用

  socketclient.c
  创建动态库工程

  在release文件夹下生成如下文件:

    socketclient.dll 动态库,函数二进制码的集合
    socketclient.lib 资源描述文件,描述 socketclient.dll

#define  _CRT_SECURE_NO_WARNINGS 
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "itcastlog.h"

typedef struct _SCK_HANDLE
{
    char    version[64];
    char    ip[128];
    int        port;
    unsigned char    *p;
    int        plen;
}SCK_HANDLE; //动态库 内部的数据类型 ,不想让测试程序(上层应用知道)
//数据类型的封装

__declspec(dllexport)
int cltSocketInit(void **handle /*out*/)
{
    int        ret = 0;
    SCK_HANDLE *hdl = NULL;
    ITCAST_LOG(__FILE__, __LINE__, LogLevel[2], ret, 
               "func cltSocketInit() Begin 22222:%d", ret);

    hdl = (SCK_HANDLE *)malloc(sizeof(SCK_HANDLE));
    if (hdl == NULL)
    {
        ret = -1;
        ITCAST_LOG(__FILE__, __LINE__, LogLevel[4], ret, 
                   "func cltSocketInit() err:%d", ret);
        return ret;
    }
    memset(hdl, 0, sizeof(SCK_HANDLE)); //把指针所指向的内存空间 赋值成 0;

    strcpy(hdl->ip, "192.168.6.254");
    hdl->port = 8081;
    *handle = hdl;

    ITCAST_LOG(__FILE__, __LINE__, LogLevel[2], ret, 
               "func cltSocketInit() End:%d \n", ret);

    return ret;
}

//客户端发报文
__declspec(dllexport)
int cltSocketSend(void *handle /*in*/, unsigned char *buf /*in*/,  
                  int buflen /*in*/)
{
    int        ret = 0;
    SCK_HANDLE *hdl = NULL;

    if (handle==NULL || buf==NULL )
    {
        ret = -1;
        ITCAST_LOG(__FILE__, __LINE__, LogLevel[4], ret, 
                   "func cltSocketSend() err:%d\n  (handle==NULL || buf==NULL ) ", 
                   ret);
        return ret;
    }

    hdl = (SCK_HANDLE *)handle;

    hdl->p = (unsigned char *)malloc(buflen *sizeof(unsigned char));
    if (hdl->p == NULL)
    {
        ret = -2;
        ITCAST_LOG(__FILE__, __LINE__, LogLevel[4], ret, 
                   "func cltSocketSend() err: buflen:%d ", 
                   buflen);
        ITCAST_LOG(__FILE__, __LINE__, LogLevel[4], ret, "func cltSocketSend() err:%d\n  (unsigned char *)malloc(buflen *sizeof(unsigned char) ", ret);
        return ret;
    }
    memcpy(hdl->p, buf, buflen);
    hdl->plen = buflen;

    return 0;
}

//客户端收报文
__declspec(dllexport)
int cltSocketRev(void *handle /*in*/, unsigned char *buf /*in*/, int *buflen /*in out*/)
{
    int        ret = 0;
    SCK_HANDLE *hdl = NULL;

    if (handle==NULL || buf==NULL  ||buflen==NULL)
    {
        ret = -1;
        ITCAST_LOG(__FILE__, __LINE__, LogLevel[4], ret, 
                   "func cltSocketRev() err:%d\n  (handle==NULL || buf==NULL ) ", 
                   ret);
        return ret;
    }
    hdl = (SCK_HANDLE *)handle;

    memcpy(buf, hdl->p, hdl->plen);
    *buflen =  hdl->plen;

    return ret;
}

//客户端释放资源
__declspec(dllexport)
int cltSocketDestory(void *handle/*in*/)
{
    int        ret = 0;
    SCK_HANDLE *hdl = NULL;

    if (handle==NULL )
    {
        ret = -1;
        ITCAST_LOG(__FILE__, __LINE__, LogLevel[4], ret, 
                   "func cltSocketDestory() err:%d\n  (handle==NULL || buf==NULL ) ", 
                   ret);
        return ret;
    }
    hdl = (SCK_HANDLE *)handle;

    if (hdl->p)
    {
        free(hdl->p);
    }
    free(hdl);

    return ret;
}


//-----------------------第二套api函数--------------------------------*/
__declspec(dllexport)
int cltSocketInit2(void **handle)
{
    return cltSocketInit(handle);
}

//客户端发报文
__declspec(dllexport)
int cltSocketSend2(void *handle, unsigned char *buf,  int buflen)
{
    return cltSocketSend(handle, buf, buflen);
}

//客户端收报文
__declspec(dllexport)
int cltSocketRev2(void *handle, unsigned char **buf, int *buflen)
{
    int        ret = 0;
    SCK_HANDLE *hdl = NULL;
    unsigned char        *tmp = NULL;

    if (handle==NULL || buf==NULL  ||buflen==NULL)
    {
        ret = -1;
        ITCAST_LOG(__FILE__, __LINE__, LogLevel[4], ret, 
                   "func cltSocketRev2() err:%d\n  (handle==NULL || buf==NULL ) ", 
                   ret);
        return ret;
    }
    hdl = (SCK_HANDLE *)handle;

    tmp = (unsigned char *)malloc(hdl->plen);
    if (tmp == NULL)
    {
        ret = -2;
        ITCAST_LOG(__FILE__, __LINE__, LogLevel[4], ret, 
                   "func cltSocketRev2() err:%d\n  (malloc err ) ", 
                   ret);
        return ret;
    }

    memcpy(tmp, hdl->p, hdl->plen);
    *buflen =  hdl->plen;

    *buf = tmp; //间接赋值
    return ret;
}

__declspec(dllexport)
int cltSocketRev2_Free(unsigned char **buf)
{
    if (buf == NULL)
    {
        return -1;
    }
    if (*buf != NULL)
    {
        free(*buf);
    }
    *buf = NULL; //*实参的地址  去间接的修改实参的值  重新初始化NULL
    return 0;
}

//客户端释放资源
__declspec(dllexport)
int cltSocketDestory2(void **handle)
{
    SCK_HANDLE *tmp = NULL;
    if (handle==NULL)
    {
        return -1;
    }
    tmp = *handle; 
    if (tmp != NULL)
    {
        if (tmp->p)
        {
            free(tmp->p);
            tmp->p = NULL;
        }
        free(tmp);
    }
    *handle = NULL; //*实参的地址  去间接的修改实参的值  重新初始化NULL

    return 0;
}

  socketclientdll.h

  socket客户端发送报文接受报文的api接口

#ifndef _INC_Demo01_H
#define _INC_Demo01_H

#ifdef  __cplusplus
extern "C" {
#endif

    //------------------第一套api接口---Begin--------------------------------//
    //客户端初始化 获取handle上下
    int cltSocketInit(void **handle /*out*/); 

    //客户端发报文
    int cltSocketSend(void *handle /*in*/, unsigned char *buf /*in*/,  int buflen /*in*/);

    //客户端收报文
    int cltSocketRev(void *handle /*in*/, unsigned char *buf /*in*/, int *buflen /*in out*/);

    //客户端释放资源
    int cltSocketDestory(void *handle/*in*/);
    //------------------第一套api接口---End-----------------------------------//


    //------------------第二套api接口---Begin--------------------------------//
    int cltSocketInit2(void **handle); 

    //客户端发报文
    int cltSocketSend2(void *handle, unsigned char *buf,  int buflen);
    //客户端收报文
    int cltSocketRev2(void *handle, unsigned char **buf, int *buflen);
    int cltSocketRev2_Free(unsigned char **buf);
    //客户端释放资源

    int cltSocketDestory2(void **handle);
    //------------------第二套api接口---End--------------------------------//

#ifdef  __cplusplus
}
#endif

#endif  /* _INC_Demo01_H */

  测试

  添加动态库

#define  _CRT_SECURE_NO_WARNINGS 
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "socketclientdll.h"
#include "memwatch.h"

int  main01()
{
    int        ret = 0;
    void    *handle = NULL;

    char buf[128]; /*in*/
    int buflen = 3;/*in*/

    char outbuf[128]; /*in*/
    int outbuflen = 3;/*in*/
    strcpy(buf, "hello, are you ok ?");

    ret = cltSocketInit(&handle /*out*/); 
    if (ret != 0)
    {
        printf("func cltSocketInit() err:%d \n", ret);
        return ret;
    }

    //客户端发报文
    ret =  cltSocketSend(handle /*in*/, buf /*in*/, buflen /*in*/);
    if (ret != 0)
    {
        printf("func cltSocketSend() err:%d \n", ret);
        return ret;
    }

    //客户端收报文
    ret =  cltSocketRev(handle /*in*/, outbuf /*in*/, &outbuflen /*in out*/);
    if (ret != 0)
    {
        printf("func cltSocketRev() err:%d \n", ret);
        return ret;
    }

    //客户端释放资源
     cltSocketDestory(handle/*in*/);

    system("pause");
    return ret ;
}


int main()
{
    int        ret = 0;
    void    *handle = NULL;

    char buf[128]; /*in*/
    int buflen = 3;/*in*/

    //char outbuf[128]; /*in*/ outbuf //常量指针
    //int outbuflen = 3;/*in*/

    char    *pout = NULL;
    int        poutlen = 0;
    strcpy(buf, "hello, are you ok ?");

    ret = cltSocketInit2(&handle); 

    //buflen = -133332;

    //客户端发报文
    ret = cltSocketSend2(handle, buf,  buflen);
    if (ret != 0)
    {
        return ret;
    }

    //客户端收报文
    ret = cltSocketRev2(handle, &pout, &poutlen);  //在动态库里面分配内存了
    if (ret != 0)
    {
        return ret;
    }
    /*
    if (pout != NULL)
    {
        free(pout);
    }
    */

     //避免野指针  把outbuf所指向的内存释放,同时把outbuf变量赋值NULL
    cltSocketRev2_Free(&pout); 

    //ret = cltSocketRev2_Free(&pout);
    //客户端释放资源

    cltSocketDestory2(&handle);
    system("pause");
    return ;
}

2、动态库升级成框架案例

  C动态库升级成框架案例

  函数指针反向调用,通过函数指针实现C语言的面向对象编程。

  回调函数:利用函数指针做函数参数,实现的一种调用机制,具体任务的实现者,可以不知道什么时候被调用。

  回调机制原理:

    当具体事件发生时,调用者通过函数指针调用具体函数。
    回调机制的将调用者和被调函数分开,两者互不依赖。
    任务的实现和任务的调用可以耦合(提前进行接口的封装和设计)。

  socketclient.c

#define  _CRT_SECURE_NO_WARNINGS 
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "itcast_comm.h"
#include "itcastlog.h"

typedef int (*EncData)(unsigned char *inData,
                       int inDataLen,
                       unsigned char *outData,
                       int *outDataLen,
                       void *Ref, int RefLen);
typedef int (*DecData)(unsigned char *inData,
                       int inDataLen,
                       unsigned char *outData,
                       int *outDataLen,
                       void *Ref, 
                       int RefLen);

typedef struct _SCK_HANDLE {
    char        version[16];
    char        serverip[16];
    int            serverport;
    unsigned char *    buf ;
    int                buflen;

    //加密函数入口地址
    EncData        encDataFunc;
    void        *enc_ref;
    int            enc_refLen;

    //加密函数入口地址
    DecData        decDataFunc;
    void        *dec_ref;
    int            dec_refLen;
}SCK_HANDLE;

//客户端初始化
ITCAST_FUNC_EXPORT(int)
cltSocketInit(void **handle) //5day after
{
    SCK_HANDLE        *sh = NULL;
    int                rv = 0;

    if (handle == NULL)
    {
        rv = -1;
        return rv;
    }
    //分配内存并初始化
    sh = (SCK_HANDLE *)malloc(sizeof(SCK_HANDLE));
    if (sh == NULL)
    {
        rv = -2;
        return rv;
    }
    memset(sh, 0, sizeof(SCK_HANDLE));

    //域赋值
    strcpy(sh->version, "0.0.1");
    strcpy(sh->serverip, "192.168.0.211");
    sh->serverport = 8888;

    //传出
    *handle = sh;
    return rv;
}

//客户端发报文
ITCAST_FUNC_EXPORT(int)
cltSocketSend(void *handle, unsigned char *buf,  int buflen)
{
    int                rv = 0;
    SCK_HANDLE        *sh = NULL;
    unsigned char    bufdata[4096];
    int                bufdatalen = 4096;

    if (handle == NULL)
    {
        rv = -4;
        return rv;
    }
    if (buf == NULL || buflen<=0)
    {
        rv = -5;
        return rv;
    }

    sh = (SCK_HANDLE *)handle;

    //数据加密 有回调函数
    if (sh->encDataFunc != NULL)
    {
        rv = sh->encDataFunc(buf, buflen, 
                             bufdata, 
                             &bufdatalen, 
                             sh->enc_ref, 
                             sh->enc_refLen);
        if (rv != 0)
        {
            return rv;
        }
        //把加密的密文 存储 handle 上下文之中
        sh->buf = (unsigned char *)malloc(sizeof(unsigned char)*bufdatalen);
        memcpy(sh->buf, bufdata, bufdatalen);
        sh->buflen = bufdatalen;
    }
    else
    {
        sh->buf = (unsigned char *)malloc(sizeof(unsigned char)*buflen);
        if (sh->buf == NULL)
        {
            rv = -6;
            return rv;
        }

        //把发送的报文数据,存储 handle 上下文之中
        memcpy(sh->buf, buf, buflen);
        sh->buflen = buflen;
    }
    return rv;
}

//客户端发报文
ITCAST_FUNC_EXPORT(int)
cltSocket_EncAndSend(void *handle, 
                     unsigned char *buf,  
                     int buflen, 
                     EncData encDataCallback, 
                     void *Ref, 
                     int RefLen)
{
    int                rv = 0;
    SCK_HANDLE        *sh = NULL;
    unsigned char    bufdata[4096];
    int                bufdatalen = 4096;

    if (handle == NULL)
    {
        rv = -4;
        return rv;
    }
    if (buf == NULL || buflen<=0)
    {
        rv = -5;
        return rv;
    }

    //先加密
    if (encDataCallback != NULL)
    {
        rv = encDataCallback(buf, 
                             buflen, 
                             bufdata, 
                             &bufdatalen, 
                             Ref, 
                             RefLen); //回调函数调用
        if (rv != 0)
        {
            return rv;
        }
    }

    sh = (SCK_HANDLE *)handle;
    sh->buf = (unsigned char *)malloc(sizeof(char)*bufdatalen);
    if (sh->buf == NULL)
    {
        rv = -6;
        return rv;
    }

    //把发送的报文数据,存储 handle 上下文之中
    memcpy(sh->buf, bufdata, bufdatalen);
    sh->buflen = bufdatalen;

    return rv;
}

//客户端收报文
ITCAST_FUNC_EXPORT(int)
cltSocketRev(void *handle, unsigned char *buf, int *buflen)
{
    int            rv = 0;
    SCK_HANDLE    *sh = NULL;

    if (handle == NULL)
    {
        rv = -4;
        return rv;
    }
    if (buflen == NULL)
    {
        rv = -5;
        return rv;
    }

    sh = (SCK_HANDLE *)handle;

    //赋值 把上下文中的数据,copy到buf空间中
    //支持二次调用,第一次调用求长度 第二次调用可以把数据copy buf中
    if (buf != NULL)
    {
        memcpy(buf, sh->buf, sh->buflen);
        //buf[ci->buflen] = '\0';
    }
    *buflen = sh->buflen;
    return rv;
}
//客户端释放资源
ITCAST_FUNC_EXPORT(int)
cltSocketDestory(void *handle)
{
    SCK_HANDLE *sh = NULL;
    sh = handle; 
    if (sh != NULL)
    {
        free(sh->buf);
        free(sh);
    }
    return 0;
}

/////////////////第二套api实现/////////////////////

//客户端初始化
ITCAST_FUNC_EXPORT(int)
cltSocketInit2(void **handle) //5day after
{
    SCK_HANDLE        *sh = NULL;
    int                rv = 0;


    if (handle == NULL)
    {
        rv = -1;
        return rv;
    }
    //分配内存并初始化
    sh = (SCK_HANDLE *)malloc(sizeof(SCK_HANDLE));
    if (sh == NULL)
    {
        rv = -2;
        return rv;
    }
    memset(sh, 0, sizeof(SCK_HANDLE));

    //域赋值
    strcpy(sh->version, "0.0.1");
    strcpy(sh->serverip, "192.168.0.211");
    sh->serverport = 8888;

    //传出
    *handle = sh;
    return rv;
}

//客户端发报文
ITCAST_FUNC_EXPORT(int)
cltSocketSend2(void *handle, unsigned char *buf,  int buflen)
{
    int                rv = 0;
    SCK_HANDLE        *sh = NULL;

    if (handle == NULL)
    {
        rv = -4;
        return rv;
    }
    if (buf == NULL || buflen<=0)
    {
        rv = -5;
        return rv;
    }

    sh = (SCK_HANDLE *)handle;
    sh->buf = (unsigned char *)malloc(sizeof(char)*buflen);
    if (sh->buf == NULL)
    {
        rv = -6;
        return rv;
    }

    //把发送的报文数据,存储 handle 上下文之中
    memcpy(sh->buf, buf, buflen);
    sh->buflen = buflen;

    return rv;
}
//客户端收报文
ITCAST_FUNC_EXPORT(int)
cltSocketRev2(void *handle, unsigned char **buf, int *buflen)
{
    int            rv = 0;
    SCK_HANDLE    *sh = NULL;

    if (handle == NULL)
    {
        rv = -4;
        return rv;
    }
    if (buflen == NULL)
    {
        rv = -5;
        return rv;
    }
    sh = (SCK_HANDLE *)handle;


    //分配内存数据传出
    *buf = (char *)malloc(sh->buflen);
    if (*buf == NULL)
    {
        rv = -6;
        return rv;
    }
    memcpy(*buf, sh->buf, sh->buflen);

    *buflen = sh->buflen;

    return rv;
}

ITCAST_FUNC_EXPORT(int)
cltSocketRev2_Free(unsigned char **buf)
{
    int rv = 0;
    unsigned char * tmp = *buf;
    if (buf == NULL)
    {
        rv = -7;
        return rv;
    }
    if (tmp != NULL)
    {
        free(tmp);
    }
    *buf = NULL;
}

//客户端释放资源
ITCAST_FUNC_EXPORT(int)
cltSocketDestory2(void **handle)
{
    SCK_HANDLE *sh = NULL;
    sh = *handle; 
    if (sh != NULL)
    {
        free(sh->buf);
        free(sh);
    }
    *handle = NULL;
    return 0;
}

ITCAST_FUNC_EXPORT(int)
cltSocketSetEncFunc(void *handle, 
                    EncData encDataFunc,
                    void  *enc_ref, 
                    int enc_refLen)
{
    SCK_HANDLE *sh = NULL;

    if (handle == NULL)
    {
        return  -1;
    }

    sh = (SCK_HANDLE *)handle;

    sh->encDataFunc = encDataFunc;
    if (enc_refLen > 0)
    {
        sh->enc_refLen = enc_refLen;
        sh->enc_ref = malloc(enc_refLen);
        memcpy(sh->enc_ref, enc_ref, enc_refLen);
    }

    return 0;
}

 

   socketclientdll.h

#ifndef _INC_Demo01_H
#define _INC_Demo01_H
#ifdef  __cplusplus
extern "C" {
#endif
    //定义一套协议
    //实现 动态库 加密解密业务模型抽象
    typedef int (*EncData)(unsigned char *inData,
                           int inDataLen,
                           unsigned char *outData,
                           int *outDataLen,
                           void *Ref, 
                           int RefLen);
    typedef int (*DecData)(unsigned char *inData,
                           int inDataLen,
                           unsigned char *outData,
                           int *outDataLen,
                           void *Ref, 
                           int RefLen);

    //------------第一套api接口---Begin-------------//
    //客户端初始化
    int cltSocketInit(void **handle /*out*/); 

    //客户端发报文
    int cltSocketSend(void *handle /*in*/, 
                      unsigned char *buf /*in*/,  
                      int buflen /*in*/);

    int cltSocket_EncAndSend(void *handle,  
                             EncData encDataCallBack, 
                             unsigned char *buf,  
                             int buflen);

    //客户端收报文
    int cltSocketRev(void *handle /*in*/, 
                     unsigned char *buf /*in*/, 
                     int *buflen /*in out*/);

    //客户端释放资源
    int cltSocketDestory(void *handle/*in*/);
    //-----------第一套api接口---End-------------//

    //-------------第二套api接口---Begin----------//
    int cltSocketInit2(void **handle); 

    //客户端发报文
    int cltSocketSend2(void *handle, 
                       unsigned char *buf,  
                       int buflen);
    //客户端收报文
    int cltSocketRev2(void *handle, 
                      unsigned char **buf, 
                      int *buflen);
    int cltSocketRev2_Free(unsigned char **buf);
    //客户端释放资源

    int cltSocketDestory2(void **handle);
    //-----------第二套api接口---End---------------//

    //实现了 把上层应用加密接口入口地址 塞入到动态库 里面
    int cltSocketSetEncFunc(void *handle, 
                            EncData encDataFunc,
                            void  *enc_ref, 
                            int enc_refLen);

#ifdef  __cplusplus
}
#endif

#endif  /* _INC_Demo01_H */

  test

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "socketclientdll.h"

//typedef int (*EncData)(unsigned char *inData,int inDataLen,unsigned char *outData,int *outDataLen,void *Ref, int RefLen);

//是厂商的加密函数
int myEncData(unsigned char *inData,
              int inDataLen,
              unsigned char *outData,
              int *outDataLen,
              void *Ref, int RefLen)
{
    memcpy(outData, "12345", 10);
    *outDataLen = 10;
    return 0;
}

int main()
{
    int                rv = 0;
    void            *handle = NULL;
    unsigned char    buf[2048];
    int                buflen = 0;

    unsigned char    buf2[2048] = {0};
    int                buflen2 = 0;

    strcpy(buf, "hello world");


    buflen = 10;
    rv = cltSocketInit(&handle);
    if (rv != 0)
    {
        printf("func cltSocketInit():%d", rv);
        return rv;
    }

    // cvtres.exe
    ///////--方法二///////////
    rv = cltSocketSetEncFunc(handle, myEncData, NULL, 0);
    if (rv != 0)
    {
        printf("func cltSocketInit():%d", rv);
        goto End;
    }

    rv = cltSocketSend(handle, buf,  buflen);
    if (rv != 0)
    {
        printf("func cltSocketSend():%d", rv);
        goto End;
    }
    ///////--方法二///////////////////////

    /*方法1 
    rv = cltSocket_EncAndSend(handle, buf,  buflen, myEncData, NULL, 0);
    if (rv != 0)
    {
        printf("func cltSocketSend_enc():%d", rv);
        goto End;
    }
    */

    rv = cltSocketRev(handle, buf2 , &buflen2);
    if (rv != 0)
    {
        printf("func cltSocketRev():%d", rv);
        goto End;
    }
    printf("\n%s", buf2);

End:

    rv = cltSocketDestory(handle);
    if (rv != 0)
    {
        printf("func cltSocketDestory():%d", rv);
        return rv;
    }

    printf("hello....\n");

    //system("pause");
    return 0;
}

 

posted @ 2021-12-29 20:07  孤情剑客  阅读(270)  评论(0)    收藏  举报