在学习安全传输平台项目总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。
10-安全传输平台项目-第11天(客户端代码移植-项目模块总结)
目录:
一、复习
二、安全传输平台项目——客户端代码移植-项目模块总结
1、图形客户端-密钥协商组件分析
2、图形客户端-物理组件集成
3、图形客户端-Linux源码对接错误调试
4、图形客户端-系统初始化
5、图形客户端-删除控件对应函数
6、图形客户端-密钥协商
7、图形客户端-密钥协商内存释放错误说明
8、总结
9、接口设计
10、文件加密原理
11、文件加密函数源码
12、数字证书、非对称加密
一、复习
1、复习-连接数据库
2、复习-网点信息管理
二、安全传输平台项目——客户端代码移植-项目模块总结
1、图形客户端-密钥协商组件分析
》SecMngClient协商客户端 界面设计及功能实现和SecMngServer配置管理 大体相同:
1)打开“VS”,新建Dialog,ID更改为:IDD_DIALOG_CLIENT,布局如下:
2)在“IDD_DIALOG_CLIENT”界面右键“添加类”,类名输入:CViewClient,基类选择:CFormView
3)使用类向导,为ListCtrl添加成员变量:
注意:自定义变量m_imageList不是通过类向导定义的,是通过代码定义的!
4)在MainFrm.cpp中OnOutbarNotify函数中打开case代码,增加调用(去掉return 0)
5)“类向导”中(ViewClient.cpp)重写OnInitialUpdate函数;和DlgNetInfo类似!
6)在“IDD_DIALOG_CLIENT”界面中为按钮设置ID并添加回调函数;
回调函数的逻辑在Linux下已经做过:借助wind图形界面(客户端与服务器密钥协商、密钥校验、密钥注销)与linux客户端 文字界面(与 服务器密钥协商、密钥校验、密钥注销)逻辑一样,所以这块代码不用写了,把Linux下的代码移植过来。当然还需要更改!
对比分析:
》分析wind客户端和服务器 与 linux客户端和服务器 4大基础组件区别:
1)统一报文编码解码 libmessagereal.so .h ---> .dll .lib .h
2)统一通信组件socket --- windows socket 通信
3)共享内存 --- windows shm 机制
4)数据库访问 (客户端无需数据库)
》代码如下:
1)报文编解码_win
>messagereal.dll
>messagereal.lib
>keymng_msg.h
#ifndef _KEYMNG_MSG_H_ #define _KEYMNG_MSG_H_ #ifdef __cplusplus extern "C" { #endif #define KeyMng_ParamErr 200 //输入参数失败 #define KeyMng_TypeErr 201 //输入类型失败 #define KeyMng_MallocErr 202 //分配内存失败 #define KeyMng_NEWorUPDATE 1 //1 密钥更新 #define KeyMng_Check 2 //2 密钥校验 #define KeyMng_Revoke 3 //3 密钥注销 ; #define ID_MsgKey_Req 60 //密钥请求报文 typedef struct _MsgKey_Req { //1 密钥更新 //2 密钥校验; //3 密钥注销 int cmdType; //报文命令码 char clientId[12]; //客户端编号 char AuthCode[16]; //认证码 char serverId[12]; //服务器端I编号 char r1[64]; //客户端随机数 }MsgKey_Req; //密钥应答报文 #define ID_MsgKey_Res 61 typedef struct _MsgKey_Res { int rv; //返回值 char clientId[12]; //客户端编号 char serverId[12]; //服务器编号 unsigned char r2[64]; //服务器端随机数 int seckeyid; //对称密钥编号 //modfy 2015.07.20 }MsgKey_Res; /* pstruct : 输入的报文数据 ; (指向相应结构体的指针) type : 输入的类型标识(函数内部通过type 得到 pstruct 所指向的报文类型) poutData: 输出的编码后的报文 ; outlen : 输出的数据长度; */ int MsgEncode( void *pStruct , /*in*/ int type, unsigned char **outData, /*out*/ int *outLen ); /* inData : 输入的编码后的数据; inLen : 输入的数据长度 ; pstruct : 输出的解码后的数据; (其空间是在内部开辟的,也需要用内部定义的free函数进行释放) type : 结构的类型标识(返回类型标识,使得调用者通过flag进行判断,将pstruct 转换为相应的结构) */ int MsgDecode( unsigned char *inData,/*in*/ int inLen, void **pStruct /*out*/, int *type /*out*/); /* 释放 MsgEncode( )函数中的outData; 方法:MsgMemFree((void **)outData, 0); 释放MsgDecode( )函数中的pstruct结构体,MsgMemFree((void **)outData, type); type : 输入参数,便于函数判断调用哪个结构体的free函数 */ int MsgMemFree(void **point,int type); #ifdef __cplusplus } #endif #endif
2)共享内存_win_Linux
>myipc_shm.h
// myipc_shm.h #ifndef _WBM_MY_SHM_H_ #define _WBM_MY_SHM_H_ #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef __cplusplus extern "C" { #endif //共享内存错误码 #define MYIPC_OK 0 //正确 #define MYIPC_ParamErr 301 //输入参数失败 #define MYIPC_NotEXISTErr 302 //共享内存不存在错误 #define MYIPC_CreateErr 303 //创建共享内存错误 //创建共享内存 若共享内存不存在,则创建 int IPC_CreatShm(int key, int shmsize, int *shmhdl); //打开共享内存 若共享内存不存在,返回错误 int IPC_OpenShm(int key, int shmsize, int *shmhdl); /*********************************************************************** 功能描述: 创建共享内存 通过种子文件 参数说明: shmname [in] 是共享内存名,系统中唯一标志 shmsize [in] 是要创建的共享内存的大小; shmhdl [out] 共享内存的句柄. 返回值: 返回0函数执行成功;非0返回错误码 ************************************************************************/ int IPC_CreatShmBySeedName(char *shmname, int shmsize, int *shmhdl); /*********************************************************************** 功能描述: 关联共享内存 参数说明: shmhdl [in] 共享的句柄 mapaddr [out] 共享内存首地址 返回值: 返回0函数执行成功;非0返回错误码 ************************************************************************/ int IPC_MapShm(int shmhdl,void **mapaddr); /*********************************************************************** 功能描述: 取消共享内存关联 参数说明: unmapaddr [in] 共享内存首地址 返回值: 返回0函数执行成功;非0返回错误码 ************************************************************************/ int IPC_UnMapShm(void *unmapaddr); /*********************************************************************** 功能描述: 删除共享内存 参数说明: shmhdl [in] 共享的句柄 返回值: 返回0函数执行成功;非0返回错误码 ************************************************************************/ int IPC_DelShm(int shmhdl); #ifdef __cplusplus } #endif #endif
>myipc_shm.cpp
//#define _OS_LINUX_ #include "stdafx.h" #define _OS_WIN_ 1 #if defined _OS_WIN_ #include <conio.h> #include <stdio.h> #include <memory.h> #include <string.h> #include <windows.h> #endif #if defined _OS_LINUX_ #include <stdio.h> #include <errno.h> #include <unistd.h> #include <memory.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/sem.h> #include <sys/msg.h> #include "myipc_shm.h" #endif #include "myipc_shm.h" int shmflag = 0; int shmkey; //创建共享内存 若共享内存不存在,则创建 若存在使用原来的 int IPC_CreatShm(int key, int shmsize, int *shmhdl) { int tmpshmhdl = 0; int ret = 0; #ifdef _OS_LINUX_ // 创建共享内存 // 若共享内存不存在则创建 // 若共享内存已存在使用原来的 tmpshmhdl = shmget(key, shmsize, IPC_CREAT|0666); if (tmpshmhdl == -1) //创建失败 { ret = MYIPC_ParamErr; printf("func shmget() err :%d ", ret); return ret; } *shmhdl = tmpshmhdl; #endif #ifdef _OS_WIN_ char shmname[512] = {0}; HANDLE m_hMapFile; sprintf(shmname, "%d", key); tmpshmhdl =(int)OpenFileMapping(FILE_MAP_WRITE, FALSE, shmname); if (tmpshmhdl <= 0) { printf("共享内存不存在, 创建共享内存 "); tmpshmhdl = (int)CreateFileMapping( (HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE, 0, shmsize, shmname); if ( tmpshmhdl == 0 ) { return MYIPC_CreateErr; } } *shmhdl = tmpshmhdl; #endif return ret; } //打开共享内存 若共享内存不存在,返回错误 //参数 无意义 可填写0 int IPC_OpenShm(int key, int shmsize, int *shmhdl) { int tmpshmhdl = 0; int ret = 0; #ifdef _OS_LINUX_ // 创建共享内存 // 若共享内存不存在则创建 // 若共享内存已存在使用原来的 tmpshmhdl = shmget(key, 0, 0); if (tmpshmhdl == -1) //打开失败 { ret = MYIPC_NotEXISTErr; //printf("func shmget() err :%d ", ret); return ret; } *shmhdl = tmpshmhdl; #endif #ifdef _OS_WIN_ char shmname[512] = {0}; sprintf(shmname, "%d", key); tmpshmhdl = (int)OpenFileMapping(FILE_MAP_WRITE, FALSE, shmname); //modify (int) if (tmpshmhdl <= 0) { ret = MYIPC_NotEXISTErr; //printf("func shmget() err :%d ", ret); return ret; } *shmhdl = tmpshmhdl; #endif return ret; } // 功能描述: 创建共享内存 // 参数说明: shmname [in] 是共享内存名,系统中唯一标志 // shmsize [in] 是要创建的共享内存的大小; // shmhdl [out] 共享内存的句柄. // 返回值: 返回0函数执行成功;非0返回错误码 int IPC_CreatShmBySeedName(char *shmseedfile, int shmsize, int *shmhdl) { int tmpshmhdl = 0; int ret = 0; #ifdef _OS_LINUX_ if(shmflag == 0) //判断接口中共享内存key是否已经存在 { shmkey = ftok(shmseedfile, 'c'); if (shmkey == -1) { perror("ftok"); return -1; } shmflag = 1; } //创建共享内存 *shmhdl = shmget(shmkey,shmsize,IPC_CREAT|0666); if (*shmhdl == -1) //创建失败 return -2; #endif #ifdef _OS_WIN_ tmpshmhdl = (int)CreateFileMapping( (HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE, 0, shmsize, shmseedfile); if ( tmpshmhdl == 0 ) { return MYIPC_CreateErr; } *shmhdl = tmpshmhdl; #endif return 0; } // 功能描述: 关联共享内存 // 参数说明: shmhdl [in] 共享的句柄 // mapaddr [out] 共享内存首地址 // 返回值: 返回0函数执行成功;非0返回错误码 int IPC_MapShm(int shmhdl, void **mapaddr) { void *tempptr = NULL; #ifdef _OS_LINUX_ //连接共享内存 tempptr = (void *)shmat(shmhdl,0,SHM_RND); if ((int)tempptr == -1) //共享内存连接失败 return -1; *mapaddr = tempptr; //导出共享内存首指针 #endif #ifdef _OS_WIN_ tempptr = MapViewOfFile((HANDLE)shmhdl, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0); if( tempptr == NULL ) return -1; *mapaddr = tempptr; #endif return 0; } // 功能描述: 取消共享内存关联 // 参数说明: unmapaddr [in] 共享内存首地址 // 返回值: 返回0函数执行成功;非0返回错误码 int IPC_UnMapShm(void *unmapaddr) { int ret = 0; #ifdef _OS_LINUX_ //取消连接共享内存 ret = shmdt((char *)unmapaddr); if (ret == -1) //取消连接失败 return -1; #endif #ifdef _OS_WIN_ ret = UnmapViewOfFile(unmapaddr); if (ret == 0) { return -1; } else { return 0; //modify } #endif return ret; } // 功能描述: 删除共享内存 // 参数说明: shmhdl [in] 共享的句柄 // 返回值: 返回0函数执行成功;非0返回错误码 int IPC_DelShm(int shmhdl) { int ret; #ifdef _OS_LINUX_ //删除共享内存 ret = shmctl(shmhdl,IPC_RMID,NULL); if(ret < 0) //删除共享内存失败 return -1; #endif #ifdef _OS_WIN_ ret = CloseHandle((HANDLE)shmhdl); if (ret == 0) return -1; #endif return ret; }
3)socket通信_win_Linux
>poolsocket.h
#ifndef _poolsocket_H_ #define _poolsocket_H_ //错误码定义 #define Sck_Ok 0 #define Sck_BaseErr 3000 #define Sck_ErrParam (Sck_BaseErr+1) #define Sck_ErrTimeOut (Sck_BaseErr+2) #define Sck_ErrPeerClosed (Sck_BaseErr+3) #define Sck_ErrMalloc (Sck_BaseErr+4) #define Sck_Err_Pool_CreateConn (Sck_BaseErr+20) //创建连接池 (没有达到最大连接数) #define Sck_Err_Pool_terminated (Sck_BaseErr+21) //已终止 #define Sck_Err_Pool_GetConn_ValidIsZero (Sck_BaseErr+22) //有效连接数是零 #define Sck_Err_Pool_HaveExist (Sck_BaseErr+22) //连接已经在池中 #define Sck_Err_Pool_ValidBounds (Sck_BaseErr+22) //有效连接数目超过了最大连接数 typedef struct _SCKClitPoolParam { char serverip[64]; int serverport; int bounds; //池容量 int connecttime; int sendtime; int revtime; }SCKClitPoolParam; //客户端 初始化 int sckClient_init(); //客户端 连接服务器 int sckClient_connect(char *ip, int port, int connecttime, int *connfd); //客户端 关闭和服务端的连接 int sckClient_closeconn(int connfd); //客户端 发送报文 int sckClient_send(int connfd, int sendtime, unsigned char *data, int datalen); //客户端 接受报文 int sckClient_rev(int connfd, int revtime, unsigned char **out, int *outlen); //1 //客户端 释放内存 int sck_FreeMem(void **buf); //客户端 释放 int sckClient_destroy(); //客户端 socket池初始化 int sckCltPool_init(void **handle, SCKClitPoolParam *param); //客户端 socket池 获取一条连接 int sckCltPool_getConnet(void *handle, int *connfd); //客户端 socket池 发送数据 int sckCltPool_send(void *handle, int connfd, unsigned char *data, int datalen); //客户端 socket池 接受数据 int sckCltPool_rev(void *handle, int connfd, unsigned char **out, int *outlen); //1 //客户端 socket池 把连接放回 socket池中 int sckCltPool_putConnet(void *handle, int connfd, int validFlag); //0正常 1 //客户端 socket池 销毁连接 int sckCltPool_destroy(void *handle); //函数声明 //服务器端初始化 int sckServer_init(int port, int *listenfd); int sckServer_accept(int listenfd, int timeout, int *connfd); //服务器端发送报文 int sckServer_send(int connfd, int timeout, unsigned char *data, int datalen); //服务器端端接受报文 int sckServer_rev(int connfd, int timeout, unsigned char **out, int *outlen); //1 int sckServer_close(int connfd); //服务器端环境释放 int sckServer_destroy(); // #ifdef __cpluspluse // } // #endif #endif
>poolsocket.cpp
// __declspec(dllexport) /* #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <signal.h> #include <sys/wait.h> #include <fcntl.h> #include <sys/time.h> #include <sys/time.h> */ #include "stdafx.h" #include "windows.h" #include "winbase.h" #include <process.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> //#include <pthread.h> #include "poolsocket.h" #include "socketlog.h" //Socket连接池结构 typedef struct _SockePoolHandle { int * fdArray; //Socket连接池 int * statusArray; //每条连接的状态 eg: statusArray[0] = 1表示 链接有效 statusArray[0] = 0表示 链接无效 int valid; //Socket有效连接数目 int nvalid; //Socket无效连接数目 int bounds; //Socket连接池的容量 char serverip[128]; int serverport; int connecttime; int sendtime; int revtime; int sTimeout; //没有连接时,等待之间 //pthread_mutex_t foo_mutex ; LPCRITICAL_SECTION pCS ; //判断连接池是否已经终止 int terminated; //1已经终止 0没有终止 }SockePoolHandle; //客户端 socket池初始化 int sckCltPool_init(void **handle, SCKClitPoolParam *param) { int ret = 0, i = 0; SockePoolHandle *hdl = NULL; //初始化 句柄 hdl = (SockePoolHandle *)malloc(sizeof(SockePoolHandle)); if (hdl == NULL) { ret = Sck_ErrMalloc; Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"func sckCltPool_init(), check malloc err"); return ret; } memset(hdl, 0, sizeof(hdl)); strcpy(hdl->serverip, param->serverip); hdl->serverport = param->serverport; hdl->connecttime = param->connecttime; hdl->sendtime = param->sendtime; hdl->revtime = param->revtime; //处理连接数 hdl->bounds = param->bounds; hdl->valid = 0; hdl->nvalid = param->bounds; hdl->sTimeout = 1; hdl->pCS = (LPCRITICAL_SECTION)malloc(sizeof(CRITICAL_SECTION)); if (hdl->pCS==NULL) { ret = Sck_ErrMalloc; Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"func sckCltPool_init(), check malloc err"); return ret; } InitializeCriticalSection(hdl->pCS); //初始化 EnterCriticalSection(hdl->pCS); //为连接句柄分配内存 hdl->fdArray = (int *)malloc( hdl->bounds * sizeof(int) ); if (hdl->fdArray == NULL) { ret = Sck_ErrMalloc; Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"func sckCltPool_init(), check malloc err"); goto END; } hdl->statusArray = (int *)malloc( hdl->bounds * sizeof(int) ); if (hdl->statusArray == NULL) { ret = Sck_ErrMalloc; Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"func sckCltPool_init(), check malloc err"); goto END; } ret = sckClient_init(); if (ret != 0) { printf("func sckClient_init() err:%d ", ret); goto END; } for (i=0; i<hdl->bounds; i++) { ret = sckClient_connect(hdl->serverip, hdl->serverport , hdl->connecttime , &(hdl->fdArray[i]) ); if (ret != 0) { Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"func sckClient_connect() err"); break; } else { hdl->statusArray[i] = 1; hdl->valid ++; //Socket有效连接数目 hdl->nvalid --; //Socket无效连接数目 } } if (hdl->valid < hdl->bounds ) //若有效连接数 小于 总数 { ret = Sck_Err_Pool_CreateConn; Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"有效连接数 小于 总数"); Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"func sckClient_init() create connect num err:%d, hdl->valid: %d , hdl->bounds:%d", ret, hdl->valid, hdl->bounds); for (i=0; i<hdl->bounds; i++) { if (hdl->statusArray[i] == 1) { sckClient_closeconn(hdl->fdArray[i]); } } } END: //pthread_mutex_unlock(& (hdl->foo_mutex) ); //解锁 LeaveCriticalSection(hdl->pCS); if (ret != 0) { if (hdl->fdArray != NULL) free(hdl->fdArray); if (hdl->statusArray != NULL) free(hdl->statusArray); free(hdl); Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"func pthread_mutex_unlock() err"); return ret; } *handle = hdl; //间接赋值 return ret; } //客户端 socket池 获取一条连接 int sckCltPool_getConnet(void *handle, int *connfd) { int ret = 0; SockePoolHandle *hdl = NULL; if (handle == NULL || connfd==NULL) { ret = Sck_ErrParam; Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"func sckCltPool_getConnet() (handle == NULL || connfd==NULL) err"); return ret; } hdl = (SockePoolHandle *)handle; //pthread_mutex_lock( &(hdl->foo_mutex) ); //流程加锁 pthread_mutex_unlock(& (hdl->foo_mutex) ); //解锁 EnterCriticalSection(hdl->pCS); //若 已终止 if (hdl->terminated == 1) { ret = Sck_Err_Pool_terminated; Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"func sckCltPool_getConnet() (terminated == 1)"); goto END; } //若 有效连数 = 0 if (hdl->valid == 0) { //usleep(hdl->sTimeout); //等上几微妙 Sleep(hdl->sTimeout); if (hdl->valid == 0) { ret = Sck_Err_Pool_GetConn_ValidIsZero; Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"func sckCltPool_getConnet() Sck_Err_Pool_GetConn_ValidIsZero err"); goto END; } //若 已终止 if (hdl->terminated == 1) { ret = Sck_Err_Pool_terminated; Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"func sckCltPool_getConnet() (terminated == 1)"); goto END; } } //判断现有连接的状态 if (hdl->statusArray[hdl->valid-1] == 0 ) { //首先断开坏掉的连接 if (hdl->fdArray[hdl->valid-1] == 0) { ret = sckClient_closeconn(hdl->fdArray[hdl->valid-1]); if (ret != 0) { Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"funcsckClient_closeconn()err"); hdl->fdArray[hdl->valid-1] = 0; //出错不做错误处理 } } //断链修复 重新连接 1次 ret = sckClient_connect(hdl->serverip, hdl->serverport, hdl->connecttime, &(hdl->fdArray[hdl->valid-1]) ); if (ret != 0) { Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret," func sckClient_connect() err 断链修复 重新连接失败"); hdl->fdArray[hdl->valid-1] = 0; goto END; } } END: if (ret == 0) { *connfd = hdl->fdArray[ --(hdl->valid) ]; //注 有效连接数 减1 } //pthread_mutex_unlock(& (hdl->foo_mutex) ); //解锁 //printf("valid=%d;nvalid=%d;bounds=%d ", hdl->valid, hdl->nvalid, hdl->bounds); LeaveCriticalSection(hdl->pCS); return ret; } //客户端 socket池 发送数据 int sckCltPool_send(void *handle, int connfd, unsigned char *data, int datalen) { int ret = 0; SockePoolHandle *hdl = NULL; if (handle==NULL || connfd<0 || data==NULL || datalen<=0 ) { ret = Sck_ErrParam; Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret," func sckCltPool_send() err (handle==NULL || connfd<0 || data==NULL || datalen<=0) "); return ret; } hdl = (SockePoolHandle *)handle; //客户端 发送报文 ret = sckClient_send(connfd, hdl->sendtime , data, datalen); if (ret != 0) { Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret," func sckClient_send() err"); return ret; } return ret; } //客户端 socket池 接受数据 int sckCltPool_rev(void *handle, int connfd, unsigned char **out, int *outlen) { int ret = 0; SockePoolHandle *hdl = NULL; if (handle==NULL || connfd<0 || out==NULL || outlen==NULL ) { ret = Sck_ErrParam; Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret," func sckCltPool_rev() err, check (handle==NULL || connfd<0 || out==NULL || outlen==NULL )"); return ret; } hdl = (SockePoolHandle *)handle; //客户端 接受报文 ret = sckClient_rev(connfd, hdl->revtime, out, outlen); //1 if (ret != 0) { Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret," func sckClient_rev() err"); return ret; } return ret; } //客户端 socket池 把连接放回 socket池中 int sckCltPool_putConnet(void *handle, int connfd, int validFlag) { int ret = 0, i = 0; SockePoolHandle *hdl = NULL; if (handle == NULL || connfd<0) { ret = Sck_ErrParam; Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret," func sckCltPool_putConnet() err, check (handle == NULL || connfd==NULL)"); goto END; } hdl = (SockePoolHandle *)handle; //pthread_mutex_lock( &(hdl->foo_mutex) ); //流程加锁 EnterCriticalSection(hdl->pCS); //若 已终止 if (hdl->terminated == 1) { ret = Sck_Err_Pool_terminated; Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret," func sckCltPool_putConnet() err, check (func sckCltPool_putConnet() (terminated == 1))"); hdl->fdArray[hdl->valid] = connfd; hdl->valid++; goto END; } //判断连接是否已经被 放进来 //判断该连接是否已经被释放 for(i=0; i<hdl->valid; i++) { if (hdl->fdArray[i] == connfd) { ret = Sck_Err_Pool_HaveExist; Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret," func sckCltPool_putConnet() err, check Sck_Err_Pool_HaveExist "); goto END; } } //判断有效连接数是否已经到达最大值 if (hdl->valid >= hdl->bounds) { ret = Sck_Err_Pool_ValidBounds ; Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret," func sckCltPool_putConnet() err, check (hdl->valid >= hdl->bounds) "); goto END; } //判断释放的连接是否有效 if (validFlag == 1) { hdl->fdArray[hdl->valid] = connfd; hdl->statusArray[hdl->valid] = 1; //连接有效 hdl->valid++; // } else { int tmpconnectfd = 0; //首先断开坏掉的连接 ret = sckClient_closeconn(connfd); if (ret != 0) { Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret," func sckClient_closeconn() err, check (hdl->valid >= hdl->bounds) "); //失败不处理 } //断链修复 重新连接 1次 若重新连接成功则再加入连接池中;若重新连接失败,则不需要加入到连接池中 ret = sckClient_connect(hdl->serverip, hdl->serverport, hdl->connecttime, &tmpconnectfd ); if (ret != 0) { Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret," func sckClient_connect() err, 断链修复 重新连接失败"); } else { //有效连接数加1 hdl->fdArray[hdl->valid] = tmpconnectfd; hdl->statusArray[hdl->valid] = 1; //连接有效 hdl->valid++; // } } END: //pthread_mutex_unlock(& (hdl->foo_mutex) ); //解锁 LeaveCriticalSection(hdl->pCS); //printf("valid=%d;nvalid=%d;bounds=%d ", hdl->valid, hdl->nvalid, hdl->bounds); return ret; } //客户端 socket池 销毁连接 int sckCltPool_destroy(void *handle) { int ret = 0, i = 0; SockePoolHandle *hdl = NULL; if (handle == NULL ) { ret = Sck_ErrParam; Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret," func sckCltPool_destroy() err, check (handle == NULL)"); return ret; } hdl = (SockePoolHandle *)handle; //pthread_mutex_lock( &(hdl->foo_mutex) ); //流程加锁 EnterCriticalSection(hdl->pCS); //若 已终止 hdl->terminated = 1; //连接池设置成终止 状态 for (i=0; i<hdl->bounds; i++) { if (hdl->fdArray[i] != 0) { sckClient_closeconn(hdl->fdArray[i]); } } if (hdl->fdArray) { free(hdl->fdArray); hdl->fdArray = NULL; } if (hdl->statusArray) { free(hdl->statusArray); hdl->statusArray = NULL; } sckClient_destroy(); //pthread_mutex_unlock(& (hdl->foo_mutex) ); //解锁 LeaveCriticalSection(hdl->pCS); free(hdl->pCS); free(hdl); //printf("valid=%d;nvalid=%d;bounds=%d ", hdl->valid, hdl->nvalid, hdl->bounds); return ret; }
>socketlog.h
//socketlog.h 日志头文件 #ifndef _SOCKET_LOG_H_ #define _SOCKET_LOG_H_ /* #define IC_NO_LOG_LEVEL 0 #define IC_DEBUG_LEVEL 1 #define IC_INFO_LEVEL 2 #define IC_WARNING_LEVEL 3 #define IC_ERROR_LEVEL 4; */ /************************************************************************/ /* const char *file:文件名称 int line:文件行号 int level:错误级别 0 -- 没有日志 1 -- debug级别 2 -- info级别 3 -- warning级别 4 -- err级别 int status:错误码 const char *fmt:可变参数 */ /************************************************************************/ //实际使用的Level extern int SocketLevel[5]; void Socket_Log(const char *file, int line, int level, int status, const char *fmt, ...); #endif
>socketlog.cpp
#include "stdafx.h" #define _CRT_SECURE_NO_WARNINGS #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdarg.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <time.h> #include "socketlog.h" #define ITCAST_DEBUG_FILE_ "socketlib.log" #define ITCAST_MAX_STRING_LEN 10240 //#define WIN32 //Level类别 #define IC_NO_LOG_LEVEL 0 #define IC_DEBUG_LEVEL 1 #define IC_INFO_LEVEL 2 #define IC_WARNING_LEVEL 3 #define IC_ERROR_LEVEL 4 int SocketLevel[5] = {IC_NO_LOG_LEVEL, IC_DEBUG_LEVEL, IC_INFO_LEVEL, IC_WARNING_LEVEL, IC_ERROR_LEVEL}; //Level的名称 char ICLevelName[5][10] = {"NOLOG", "DEBUG", "INFO", "WARNING", "ERROR"}; static int ITCAST_Error_GetCurTime(char* strTime) { struct tm* tmTime = NULL; size_t timeLen = 0; time_t tTime = 0; tTime = time(NULL); tmTime = localtime(&tTime); //timeLen = strftime(strTime, 33, "%Y(Y)%m(M)%d(D)%H(H)%M(M)%S(S)", tmTime); timeLen = strftime(strTime, 33, "%Y.%m.%d %H:%M:%S", tmTime); return timeLen; } static int ITCAST_Error_OpenFile(int* pf) { char fileName[1024]; memset(fileName, 0, sizeof(fileName)); #ifdef WIN32 sprintf(fileName, "c:\itcast\%s",ITCAST_DEBUG_FILE_); #else sprintf(fileName, "%s/log/%s", getenv("HOME"), ITCAST_DEBUG_FILE_); #endif /* *pf = open(fileName, O_WRONLY|O_CREAT|O_APPEND, 0666); if(*pf < 0) { return -1; } */ *pf = (int)fopen(fileName, "w+"); if (*pf < 0) { return -1; } return 0; } static void ITCAST_Error_Core(const char *file, int line, int level, int status, const char *fmt, va_list args) { char str[ITCAST_MAX_STRING_LEN]; int strLen = 0; char tmpStr[64]; int tmpStrLen = 0; int pf = 0; //初始化 memset(str, 0, ITCAST_MAX_STRING_LEN); memset(tmpStr, 0, 64); //加入LOG时间 tmpStrLen = ITCAST_Error_GetCurTime(tmpStr); tmpStrLen = sprintf(str, "[%s] ", tmpStr); strLen = tmpStrLen; //加入LOG等级 tmpStrLen = sprintf(str+strLen, "[%s] ", ICLevelName[level]); strLen += tmpStrLen; //加入LOG状态 if (status != 0) { tmpStrLen = sprintf(str+strLen, "[ERRNO is %d] ", status); } else { tmpStrLen = sprintf(str+strLen, "[SUCCESS] "); } strLen += tmpStrLen; //加入LOG信息 tmpStrLen = vsprintf(str+strLen, fmt, args); strLen += tmpStrLen; //加入LOG发生文件 tmpStrLen = sprintf(str+strLen, " [%s]", file); strLen += tmpStrLen; //加入LOG发生行数 tmpStrLen = sprintf(str+strLen, " [%d] ", line); strLen += tmpStrLen; //打开LOG文件 if(ITCAST_Error_OpenFile(&pf)) { return ; } //写入LOG文件 // write(pf, str, strLen); fwrite(str, 1, strLen, (FILE *)pf); //IC_Log_Error_WriteFile(str); //关闭文件 fclose((FILE *)pf); return ; } void Socket_Log(const char *file, int line, int level, int status, const char *fmt, ...) { va_list args; //判断是否需要写LOG // if(level!=IC_DEBUG_LEVEL && level!=IC_INFO_LEVEL && level!=IC_WARNING_LEVEL && level!=IC_ERROR_LEVEL) if(level == IC_NO_LOG_LEVEL) { return ; } //调用核心的写LOG函数 va_start(args, fmt); ITCAST_Error_Core(file, line, level, status, fmt, args); va_end(args); return ; }
>socketutil.h
// socketutil.h #ifndef _socketutil_H_ #define _socketutil_H_ #ifdef __cplusplus extern 'C' { #endif #include <stdio.h> #include <stdlib.h> void activate_nonblock(int fd); void deactivate_nonblock(int fd); int read_timeout(int fd, unsigned int wait_seconds); int write_timeout(int fd, unsigned int wait_seconds); int accept_timeout(int fd, struct sockaddr_in *addr, unsigned int wait_seconds); int connect_timeout(int fd, struct sockaddr_in *addr, unsigned int wait_seconds); int readn(int fd, void *buf, size_t count); int writen(int fd, const void *buf, size_t count); int recv_peek(int sockfd, void *buf, size_t len); int readline(int sockfd, void *buf, size_t maxline); #ifdef __cpluspluse } #endif #endif /* _SYS_UTIL_H_ */
>socketutil.cpp
#include "stdafx.h" #include <stdlib.h> #include <stdio.h> #include <winsock2.h> #include <stdio.h> #include <string.h> #include <time.h> #include <errno.h> #include "poolsocket.h" #include "socketlog.h" #define ssize_t int #define socklen_t int // //readn - 读取固定字节数 //@fd: 文件描述符 //@buf: 接收缓冲区 //@count: 要读取的字节数 //成功返回count,失败返回-1,读到EOF返回<count // int readn(int fd, void *buf, size_t count) { size_t nleft = count; int nread; char *bufp = (char*)buf; while (nleft > 0) { //if ((nread = read(fd, bufp, nleft)) < 0) if ((nread = recv(fd, bufp, nleft, 0)) < 0) { if (errno == EINTR) continue; return -1; } else if (nread == 0) return count - nleft; bufp += nread; nleft -= nread; } return count; } // //writen - 发送固定字节数 //@fd: 文件描述符 //@buf: 发送缓冲区 //@count: 要读取的字节数 //成功返回count,失败返回-1 // int writen(int fd, const void *buf, size_t count) { size_t nleft = count; ssize_t nwritten; char *bufp = (char*)buf; while (nleft > 0) { //if ((nwritten = write(fd, bufp, nleft)) < 0) if ((nwritten = send(fd, bufp, nleft, 0)) < 0) { if (errno == EINTR) continue; return -1; } else if (nwritten == 0) continue; bufp += nwritten; nleft -= nwritten; } return count; } // //recv_peek - 仅仅查看套接字缓冲区数据,但不移除数据 //@sockfd: 套接字 //@buf: 接收缓冲区 //@len: 长度 //成功返回>=0,失败返回-1 // int recv_peek(int sockfd, void *buf, size_t len) { while (1) { int ret = recv(sockfd, (char *)buf, len, MSG_PEEK); if (ret == -1 && errno == EINTR) continue; return ret; } } // //activate_noblock - 设置I/O为非阻塞模式 //@fd: 文件描符符 // int activate_nonblock(int fd) { int ret = 0; /* int flags = fcntl(fd, F_GETFL); if (flags == -1) { ret = flags; Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"func activate_nonblock() err"); return ret; } flags |= O_NONBLOCK; ret = fcntl(fd, F_SETFL, flags); if (ret == -1) { Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"func activate_nonblock() err"); return ret; } */ int flags = 1; if (ioctlsocket(fd, FIONBIO, (u_long *)&flags)) { ret = -1; Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"func ioctlsocket() err 设置为非阻塞模式失败"); return ret; } return ret; } // //deactivate_nonblock - 设置I/O为阻塞模式 //@fd: 文件描符符 // int deactivate_nonblock(int fd) { int ret = 0; /* int flags = fcntl(fd, F_GETFL); if (flags == -1) { ret = flags; Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"func deactivate_nonblock() err"); return ret; } flags &= ~O_NONBLOCK; ret = fcntl(fd, F_SETFL, flags); if (ret == -1) { Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"func deactivate_nonblock() err"); return ret; }*/ int flags = 0; if(ioctlsocket(fd, FIONBIO, (u_long *)&flags)) { ret = -1; Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret, "func ioctlsocket() err 设置为阻塞模式失败 "); return ret; } return ret; } // //connect_timeout - connect //@fd: 套接字 //@addr: 要连接的对方地址 //@wait_seconds: 等待超时秒数,如果为0表示正常模式 //成功(未超时)返回0,失败返回-1,超时返回-1并且errno = ETIMEDOUT // static int connect_timeout(int fd, struct sockaddr_in *addr, unsigned int wait_seconds) { int ret; socklen_t addrlen = sizeof(struct sockaddr_in); if (wait_seconds > 0) activate_nonblock(fd); ret = connect(fd, (struct sockaddr*)addr, addrlen); if (ret < 0 && errno == EINPROGRESS || ret<0 && WSAGetLastError()==WSAEWOULDBLOCK ) //win和linux下 { //printf("11111111111111111111 "); fd_set connect_fdset; struct timeval timeout; FD_ZERO(&connect_fdset); FD_SET(fd, &connect_fdset); timeout.tv_sec = wait_seconds; timeout.tv_usec = 0; do { // 一但连接建立,则套接字就可写 所以connect_fdset放在了写集合中 ret = select(fd + 1, NULL, &connect_fdset, NULL, &timeout); } while (ret < 0 && errno == EINTR); if (ret == 0) { ret = -1; errno = ETIMEDOUT; } else if (ret < 0) return -1; else if (ret == 1) { //printf("22222222222222222 "); // ret返回为1(表示套接字可写),可能有两种情况,一种是连接建立成功,一种是套接字产生错误, // 此时错误信息不会保存至errno变量中,因此,需要调用getsockopt来获取。 int err; socklen_t socklen = sizeof(err); int sockoptret = getsockopt(fd, SOL_SOCKET, SO_ERROR, (char *)&err, &socklen); if (sockoptret == -1) { return -1; } if (err == 0) { //printf("3333333333333 "); ret = 0; } else { //printf("4444444444444444:%d ", err); errno = err; ret = -1; } } } if (wait_seconds > 0) { deactivate_nonblock(fd); } return ret; } // //write_timeout - 写超时检测函数,不含写操作 //@fd: 文件描述符 //@wait_seconds: 等待超时秒数,如果为0表示不检测超时 //成功(未超时)返回0,失败返回-1,超时返回-1并且errno = ETIMEDOUT // int write_timeout(int fd, unsigned int wait_seconds) { int ret = 0; if (wait_seconds > 0) { fd_set write_fdset; struct timeval timeout; FD_ZERO(&write_fdset); FD_SET(fd, &write_fdset); timeout.tv_sec = wait_seconds; timeout.tv_usec = 0; do { ret = select(fd + 1, NULL, &write_fdset, NULL, &timeout); } while (ret < 0 && errno == EINTR); if (ret == 0) { ret = -1; errno = ETIMEDOUT; } else if (ret == 1) ret = 0; } return ret; } // //read_timeout - 读超时检测函数,不含读操作 //@fd: 文件描述符 //@wait_seconds: 等待超时秒数,如果为0表示不检测超时 //成功(未超时)返回0,失败返回-1,超时返回-1并且errno = ETIMEDOUT // int read_timeout(int fd, unsigned int wait_seconds) { int ret = 0; if (wait_seconds > 0) { fd_set read_fdset; struct timeval timeout; FD_ZERO(&read_fdset); FD_SET(fd, &read_fdset); timeout.tv_sec = wait_seconds; timeout.tv_usec = 0; //select返回值三态 //1 若timeout时间到(超时),没有检测到读事件 ret返回=0 //2 若ret返回<0 && errno == EINTR 说明select的过程中被别的信号中断(可中断睡眠原理) //2-1 若返回-1,select出错 //3 若ret返回值>0 表示有read事件发生,返回事件发生的个数 do { ret = select(fd + 1, &read_fdset, NULL, NULL, &timeout); } while (ret < 0 && errno == EINTR); if (ret == 0) { ret = -1; errno = ETIMEDOUT; } else if (ret == 1) ret = 0; } return ret; } //函数声明 //客户端环境初始化 int sckClient_init() { int ret = 0; WSADATA wsaData; struct sockaddr_in servaddr; ret = WSAStartup(MAKEWORD(2, 2), &wsaData); if (ret != NO_ERROR) { Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"func WSAStartup() err"); return ret; } return 0; } int sckClient_connect(char *ip, int port, int connecttime, int *connfd) { int ret = 0; int sockfd; struct sockaddr_in servaddr; if (ip==NULL || connfd==NULL || port<=0 || port>65537 || connecttime < 0) { ret = Sck_ErrParam; Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"func sckClient_connect() err, check (ip==NULL || connfd==NULL || port<=0 || port>65537 || connecttime < 0)"); return ret; } // sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (sockfd < 0) { ret = errno; printf("func socket() err: %d ", ret); return ret; } memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(port); servaddr.sin_addr.s_addr = inet_addr(ip); ret = connect_timeout(sockfd, (struct sockaddr_in*) (&servaddr), (unsigned int )connecttime); if (ret < 0) { if (ret==-1 && errno == ETIMEDOUT) { ret = Sck_ErrTimeOut; return ret; } else { printf("func connect_timeout() err: %d ", ret); Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"func connect_timeout() err"); } return ret; } *connfd = sockfd; return ret; } //客户端发送报文 int sckClient_send(int connfd, int sendtime, unsigned char *data, int datalen) { int ret = 0; if (data == NULL || datalen <= 0) { ret = Sck_ErrParam; Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"func sckClient_send() err, check (data == NULL || datalen <= 0)"); return ret; } ret = write_timeout(connfd, sendtime); if (ret == 0) { int writed = 0; int netlen = 0; unsigned char *netdata = ( unsigned char *)malloc(datalen + 4); if ( netdata == NULL) { ret = Sck_ErrMalloc; printf("func sckClient_send() mlloc Err:%d ", ret); return ret; } netlen = htonl(datalen); memcpy(netdata, &netlen, 4); memcpy(netdata+4, data, datalen); //writed = writen(connfd, netdata, datalen + 4); writed = send(connfd, (const char *)netdata, datalen + 4, 0); if (writed < (datalen + 4) ) { if (netdata != NULL) { free(netdata); netdata = NULL; } return writed; } if (netdata != NULL) //wangbaoming 20150630 modify bug { free(netdata); netdata = NULL; } } if (ret < 0) { //失败返回-1,超时返回-1并且errno = ETIMEDOUT if (ret == -1 && errno == ETIMEDOUT) { ret = Sck_ErrTimeOut; printf("func sckClient_send() mlloc Err:%d ", ret); return ret; } return ret; } return ret; } //客户端端接受报文 int sckClient_rev(int connfd, int revtime, unsigned char **out, int *outlen) { int ret = 0; unsigned char *tmpBuf = NULL; int netdatalen = 0; int n; if (out==NULL || outlen==NULL) { ret = Sck_ErrParam; printf("func sckClient_rev() timeout , err:%d ", Sck_ErrTimeOut); return ret; } ret = read_timeout(connfd, revtime ); //bugs modify bombing if (ret != 0) { if (ret==-1 || errno == ETIMEDOUT) { ret = Sck_ErrTimeOut; Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"func read_timeout() timeout"); return ret; } else { Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"func read_timeout() err"); return ret; } } ret = readn(connfd, &netdatalen, 4); //读包头 4个字节 if (ret == -1) { //printf("func readn() err:%d ", ret); Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"func readn() err"); return ret; } else if (ret < 4) { ret = Sck_ErrPeerClosed; //printf("func readn() err peer closed:%d ", ret); Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"func readn() err, peer closed"); return ret; } n = ntohl(netdatalen); tmpBuf = (unsigned char *)malloc(n+1); if (tmpBuf == NULL) { ret = Sck_ErrMalloc; Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"malloc() err"); return ret; } ret = readn(connfd, tmpBuf, n); //根据长度读数据 if (ret == -1) { //printf("func readn() err:%d ", ret); Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"readn() err"); return ret; } else if (ret < n) { ret = Sck_ErrPeerClosed; //printf("func readn() err peer closed:%d ", ret); Socket_Log(__FILE__, __LINE__,SocketLevel[4], ret,"func readn() err, peer closed"); return ret; } *out = tmpBuf; *outlen = n; tmpBuf[n] = '