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

浙公网安备 33010602011771号