int _tmain( void ) { int *a = new int[MAX*100]; int *b = new int[MAX*100]; int f = GetTickCount(); myMemcpy( b, a, sizeof( int ) * MAX * 100 ); printf( "一字节, 用了多少时间\t%d\n", GetTickCount() - f ); f = GetTickCount(); myMemcpy_oneByte( b, a, sizeof( int ) * MAX * 100 ); printf( "块, 用了多少时间\t%d\n", GetTickCount() - f ); // printf( "%d\n", myMemcmp( a, b, sizeof(int)*10 ) ); // myMemset( b, 1, sizeof(int)*10 ); for ( int i = 0; i < 10; ++i ) { printf( "%d ", b[i] ); } printf( "\n" ); delete[] a; delete[] b; return 0; }
int _tmain(int argc, _TCHAR* argv[]) { int c[10] = { 1,2,3,4,5,6,7,8,9,10 }; int d[10]; myMemcpy( d, c, sizeof( int )*10 ); outputArray( c, 10 ); outputArray( d, 10 ); printf( "%d\n", myMemcmp( c, d, sizeof( int )*10 ) ); myMemmove( c, &c[2], sizeof( int )*8 ); outputArray( c, 10 ); myMemmove( &c[2], c, sizeof( int )*8 ); outputArray( c, 10 ); myMemset( d, 0, sizeof( int )*10 ); outputArray( d, 10 ); char a[100] = "123456789"; char b[100] = "abcdefghijklmn"; printf( "%d\n", myStrlen( a ) ); printf( "%d\n", myStrlen( b ) ); printf( "%s\n", myStrcat( b, a ) ); //printf( "%s\n", myStrcat( a, &a[2] ) ); //printf( "%s\n", myStrcat( &a[2], a ) ); printf( "%s\n", a ); printf( "%d\n", myStrcmp( b, a ) ); printf( "%s\n", myStrcpy( b, a ) ); printf( "%s\n", myStrmove( a, &a[3] ) ); printf( "%s\n", myStrmove( &a[4], a ) ); printf( "%s\n", a ); return 0; }
/* *每个socket对应的线程的入口函数,客户端的socket信息处理.主要是区分web端和一般的lmt端 *此线程针对单独的客户端进行处理 */ void * proClientSocket(void *socketHandle) { bool bWebType = false; //是否为web类型 int iErrorCount = 0; //计数器 int i = 0; u_short iClientID = CARICCP_MAX_SHORT; CSocketHandle *socket_handle = ((CSocketHandle *) socketHandle); //SOCKET sock_client = socket_handle->sock_client;//此socket需要保持起来 //sockaddr_in addr_client = socket_handle->addr_client; //int nNetTimeout=3000;//3秒 //接收时限,此处设置会影响网络状态的情况判断 //setsockopt(sock_client,SOL_SOCKET,SO_RCVTIMEO,(char *)&nNetTimeout,sizeof(int)); //int nZero=0; //setsockopt(sock_client,SOL_SOCKET,SO_RCVBUF,(char *)&nZero,sizeof(int)); char *pClientIP; int sock_client = socket_handle->sock_client; //此socket需要保持起来 #if defined(_WIN32) || defined(WIN32) struct sockaddr_in addr_client = socket_handle->addr_client; pClientIP = inet_ntoa(addr_client.sin_addr); #else struct sockaddr addr_client = socket_handle->addr_client; //pClientIP = /*inet_ntoa(addr_client)*/addr_client.sa_data; //要获得client端的ip地址,必须把sockaddr结构强制转换成sockaddr_in结构,因为字节大小是相同的 pClientIP = inet_ntoa(((struct sockaddr_in *) (&addr_client))->sin_addr); //打印16进制的mac地址信息 //printf("%02x:%02x:%02x:%02x:%02x:%02x\n", // (unsigned char)addr_client.sa_data[0], // (unsigned char)addr_client.sa_data[1], // (unsigned char)addr_client.sa_data[2], // (unsigned char)addr_client.sa_data[3], // (unsigned char)addr_client.sa_data[4], // (unsigned char)addr_client.sa_data[5]); #endif //及时释放销毁当前socket句柄对象 CARI_CCP_VOS_DEL(socket_handle); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "+++ begin :Succeed linked with client(IP :%s, socketID :%d).\n", pClientIP, sock_client); //定义socket的三元组 socket3element clientSocketElement;//是否需要新创建,每个线程独享的临时变量 initSocket3element(clientSocketElement); clientSocketElement.socketClient = sock_client;//保存此socket号 clientSocketElement.addr = addr_client; //方式1: 分配客户端号,此处预先分配好,等待client下发命令查询的时候直接返回即可 //iClientID = CModuleManager::getInstance()->assignClientID(); //clientSocketElement.sClientID = iClientID; //方式2: client下发命令的时候再进行分配,考虑到以前使用的id号能重用 //目前采用这种方式 //把此客户端的socket保存起来 CModuleManager::getInstance()->saveSocket(clientSocketElement); //switch_status_t ret; int recvbytes = 0;//命名接收处理结果 #ifdef WIN32 #else //test 字符转换 CodeConverter cc = CodeConverter("gb2312","UTF-8"); #endif //针对于固定的客户端,对应的线程一直循环处理,设置时限/监测连接是否正常 while (loopFlag){//使用循环标识控制 bool bWeb = false; char recvBuf[sizeof(common_CmdReq_Frame)]; memset(recvBuf, 0, sizeof(recvBuf)); recvbytes = recv(sock_client, recvBuf, sizeof(recvBuf), 0); //要保证是阻塞模式的,如果客户端(异常)退出,会导致死循环 //网络出现异常,网络中断 if (-1 == recvbytes) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "--- end :Disconnect with client (IP :%s, socketID :%d)! \n", pClientIP, sock_client); break; } //收到的数据帧错误或客户端退出,或者初始建立连接,此时收到的数据帧的大小都是0 if (0 == recvbytes) { iErrorCount ++; //连续收到不正确的数据N次,就要退出循环,重新等待客户端的连接 if (CARICCP_MAX_ERRRORFRAME_COUNT < iErrorCount) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "--- end :Client %s already exited.\n", pClientIP); iErrorCount = 0; break; } continue; } //shutdown指令 if (shutdownFlag){ break; } ////////////////////////////////////////////////////////////////////////// //帧的销毁遵守:谁调用谁负责销毁!!!!!!!!!!!!!!!!!!! //关键的命令逻辑处理,逆解析来自客户端的请求帧 //新建客户端的请求帧,由调用者负责清除 common_CmdReq_Frame *clientReqFrame = CARI_CCP_VOS_NEW(common_CmdReq_Frame); initCommonRequestFrame(clientReqFrame); //add by xxl 2010-5-5: 需要判断一下此命令是来自web还是一般的client if(!bWebType){ char chHeader = recvBuf[0]; if ('[' ==chHeader){//判断是否为web发送的命令格式 bWeb = true; } } //需要重新解析构造请求帧,根据字符串进行转换 if (bWebType || bWeb){ string strres = recvBuf,strHeader,strCmd,strParam,strVal,strName; int ival =0; int index = strres.find_first_of("]"); strHeader = strres.substr(1,index-1); strCmd= strres.substr(index+1); //1 先构造消息头 vector<string> resultVec; splitString(strHeader, ",", resultVec); vector<string>::const_iterator it = resultVec.begin(); for (;it != resultVec.end(); it++){ strVal = *it; index = strVal.find_first_of("="); if (0 < index){ strName = strVal.substr(0,index); strVal = strVal.substr(index+1); trim(strName); trim(strVal); //解析关键的参数 if(isEqualStr("clientID",strName)){ clientReqFrame->header.sClientID = 0;//web的比较固定 } else if(isEqualStr("modId",strName)){ clientReqFrame->header.sClientChildModID = stringToInt(strVal.c_str()); } else if(isEqualStr("cmdID",strName)){ clientReqFrame->body.iCmdCode = stringToInt(strVal.c_str()); } else if(isEqualStr("logUserName",strName)){ myMemcpy(clientReqFrame->header.strLoginUserName,strVal.c_str(),strVal.length()); } } }//end for //2 再解析命令名和参数区 strName = ""; trim(strCmd); index = strCmd.find_first_of(":"); if (0 < index){ strName = strCmd.substr(0,index); strParam = strCmd.substr(index+1); } else{ strParam = strCmd; } myMemcpy(clientReqFrame->body.strCmdName,strName.c_str(),strName.length()); myMemcpy(clientReqFrame->param.strParamRegion,strParam.c_str(),CARICCP_MIN(strParam.length(),CARICCP_MAX_LENGTH)); //3 其他区域的初始化 clientReqFrame->body.bSynchro = 1; clientReqFrame->header.sClientID = 0;//web的比较固定 //4 重新设置socket,只需要设置一次即可 if(!bWebType){ bWebType = true; //重新设置clientID号 CModuleManager::getInstance()->eraseSocket(clientSocketElement.socketClient); clientSocketElement.sClientID = 0;//默认情况为CARICCP_MAX_SHORT CModuleManager::getInstance()->saveSocket(clientSocketElement); } } else{//一般的lmt,按照以前的方式处理 memcpy(clientReqFrame,recvBuf,sizeof(recvBuf)); } //add by xxl 2010-5-5 end //char strParamRegion[CARICCP_MAX_LENGTH]; #ifdef WIN32 #else //printf("before: %s\n",clientReqFrame->param.strParamRegion); ////test 字符转换 //char out[CARICCP_MAX_LENGTH]; //memset(out,0,sizeof(out)); //cc.convert(clientReqFrame->param.strParamRegion, CARICCP_MAX_LENGTH,out,CARICCP_MAX_LENGTH); //printf("convert: %s\n",out); //memset(clientReqFrame->param.strParamRegion,0,sizeof(clientReqFrame->param.strParamRegion)); //myMemcpy(clientReqFrame->param.strParamRegion,out,sizeof(out)); //printf("after: %s\n",clientReqFrame->param.strParamRegion); #endif //如果此命令执行时间过长,此处会产生阻塞,当前客户端一直收不到信息!!!!!!!!! //如果再另起线程处理,将不能保证命令执行的有序性,所以上述情况还是较少的 //不必再过多考虑!!!! //由请求帧的处理模块(入口函数)负责细节处理 //帧的销毁遵守:谁调用谁负责销毁!!!!!!!!!!!!!!!!!!!!!! CMsgProcess::getInstance()->proCmd(sock_client, clientReqFrame); //结果集合的发送不再此处设计,直接放到对应的syncProCmd函数中 //另外,如果结果集分块发送显示,此处也不适合 //发送send单独考虑 //如何保证结果集能正确的发送给对应的客户端呢??? iErrorCount = 0; }//end while(client端循环获得请求帧) //如果是强制退出(shutdown命令操作),不需要考虑释放client id号等 if (!shutdownFlag){ //先释放client id号 CModuleManager::getInstance()->releaseClientIDBySocket(sock_client); //下面进行清除客户端连接,从保存的容器中清除掉 CModuleManager::getInstance()->eraseSocket(sock_client); //关闭当前客户端的socket CARI_CLOSE_SOCKET(sock_client); } //登录的用户数量减少 global_client_num--; //线程实例清除掉 //CModuleManager::getInstance()->eraseThrd(sock_client); //退出重连接的线程 //pthread_exit(NULL); return NULL; //return也会导致本函数所在的线程退出 }
/*重新启动服务器 */ int CBaseModule::reboot(inner_CmdReq_Frame*& inner_reqFrame, inner_ResultResponse_Frame*& inner_RespFrame) { int iRes = CARICCP_SUCCESS_STATE_CODE; string strDec; int notifyCode = CARICCP_NOTIFY_REBOOT; string strNotifyCode = ""; string strClientID = intToString(inner_reqFrame->header.sClientID); string strCode = intToString(inner_reqFrame->body.iCmdCode); string strCmdName = inner_reqFrame->body.strCmdName; char *pChNotifyNode = NULL,*chDec = NULL; char *chReboot = "0"; //涉及到通知类型的处理:命令属于通知类型,需要广播通知其他客户端 switch_event_t *notifyInfoEvent = NULL; string strModel,strParamName,strChinaName; string strTmp; //model strParamName = "model";//model strChinaName = getValueOfDefinedVar(strParamName); strModel = getValue(strParamName, inner_reqFrame); if (0 == strModel.size()) { //模式为空,返回错误信息 strDec = getValueOfDefinedVar("PARAM_NULL_ERROR"); chDec = switch_mprintf(strDec.c_str(), strChinaName.c_str()); inner_RespFrame->header.iResultCode = CARICCP_ERROR_STATE_CODE; myMemcpy(inner_RespFrame->header.strResuleDesc, strDec.c_str(), sizeof(inner_RespFrame->header.strResuleDesc)); switch_safe_free(chDec); goto end_flag; } if (isEqualStr("host",strModel)){ chReboot = "1"; //描述信息 strDec = getValueOfDefinedVar("HOST_REBOOT"); } else{ chReboot = "0"; strDec = getValueOfDefinedVar("SERVER_REBOOT"); } //if (SWITCH_STATUS_SUCCESS != switch_event_create(¬ifyInfoEvent, CARICCP_EVENT_STATE_NOTIFY)) { if (SWITCH_STATUS_SUCCESS != switch_event_create_subclass(¬ifyInfoEvent, SWITCH_EVENT_CUSTOM, CARI_CCP_EVENT_NAME)) { //此时还是按照成功处理 goto end_flag; } //通知码 notifyCode = CARICCP_NOTIFY_REBOOT; //结果码和结果集 pChNotifyNode = switch_mprintf("%d", notifyCode); strNotifyCode = pChNotifyNode; switch_event_add_header_string(notifyInfoEvent, SWITCH_STACK_BOTTOM, CARICCP_NOTIFY, "1"); //通知标识 switch_event_add_header_string(notifyInfoEvent, SWITCH_STACK_BOTTOM, CARICCP_RETURNCODE, strNotifyCode.c_str()); //返回码=通知码 switch_event_add_header_string(notifyInfoEvent, SWITCH_STACK_BOTTOM, CLIENT_ID, strClientID.c_str()); //客户端号 switch_event_add_header_string(notifyInfoEvent, SWITCH_STACK_BOTTOM, CARICCP_CMDCODE, strCode.c_str()); // switch_event_add_header_string(notifyInfoEvent, SWITCH_STACK_BOTTOM, CARICCP_CMDNAME, strCmdName.c_str()); switch_event_add_header_string(notifyInfoEvent, SWITCH_STACK_BOTTOM, CARICCP_RESULTDESC, strDec.c_str()); //描述信息 //发送通知---------------------- cari_net_event_notify(notifyInfoEvent); //释放内存 switch_event_destroy(¬ifyInfoEvent); switch_safe_free(pChNotifyNode); //为了返回给客户端能显示特殊颜色,此处的返回码不为0,为CARICCP_NOTIFY_REBOOT inner_RespFrame->header.iResultCode = CARICCP_NOTIFY_REBOOT; myMemcpy(inner_RespFrame->header.strResuleDesc, strDec.c_str(), strlen(strDec.c_str()));//返回的描述信息 end_flag: //然后再重新启动一个线程来处理重启,因为本命令返回的结果还没有广播给所有的client,服务器就开始重启了 //可以限制重启时间间隔,保证结果能返回即可. pthread_t pth; int iRet= pthread_create(&pth,NULL,thread_reboot,(void *)chReboot); if(CARICCP_SUCCESS_STATE_CODE != iRet){ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Creat reboot thred failed!"); } //#if defined(_WIN32) || defined(WIN32) // cari_common_excuteSysCmd("shutdown /r"); //#else // for (int i=0;i<3;i++){ // cari_common_excuteSysCmd("sync");//加快数据更新,将内存中的数据写入到磁盘中,建议如此使用 // } // cari_common_excuteSysCmd("reboot");//当前linux系统不支持shutdown命令(shutdown -rt 10) //#endif return iRes; }
/*登录命令 */ int CBaseModule::login(inner_CmdReq_Frame *&inner_reqFrame, inner_ResultResponse_Frame *&inner_RespFrame)//输出参数,响应帧 { int iRes = CARICCP_ERROR_STATE_CODE; //如果此命令又涉及到其他子模块的处理,如何?????? //当成内部命令--------------------------------- string strParamName, strValue,strDec,strChinaName; char* chDec = NULL; //获取用户名和用户的密码 string strUserName,strPwd; string strTmp; strParamName = "loginName";//用户名 strChinaName = getValueOfDefinedVar(strParamName); strUserName = getValue(strParamName, inner_reqFrame); if (0 == strUserName.size()) { //用户名字为空,返回错误信息 strDec = getValueOfDefinedVar("PARAM_NULL_ERROR"); chDec = switch_mprintf(strDec.c_str(), strChinaName.c_str()); inner_RespFrame->header.iResultCode = CARICCP_ERROR_STATE_CODE; myMemcpy(inner_RespFrame->header.strResuleDesc, strDec.c_str(), sizeof(inner_RespFrame->header.strResuleDesc)); switch_safe_free(chDec); goto end; } strParamName = "loginPwd";//用户密码 strChinaName = getValueOfDefinedVar(strParamName); strPwd = getValue(strParamName, inner_reqFrame); if (0 == strPwd.length()) { //用户密码,返回错误信息 strDec = getValueOfDefinedVar("PARAM_NULL_ERROR"); chDec = switch_mprintf(strDec.c_str(), strChinaName.c_str());//switch_mprintf(str_NULL_Error.c_str(),strName)出错,为什么???????? inner_RespFrame->header.iResultCode = CARICCP_ERROR_STATE_CODE; myMemcpy(inner_RespFrame->header.strResuleDesc, strDec.c_str(), sizeof(inner_RespFrame->header.strResuleDesc)); switch_safe_free(chDec); goto end; } //mod by xxl 2010-5-19 :增强对操作用户的处理问题 //检查此用户是否存在 if (!isLoginSuc(strUserName,strPwd)){ strDec = getValueOfDefinedVar("LOGIN_ERROR"); inner_RespFrame->header.iResultCode = CARICCP_ERROR_STATE_CODE; myMemcpy(inner_RespFrame->header.strResuleDesc, strDec.c_str(), sizeof(inner_RespFrame->header.strResuleDesc)); goto end; } iRes = CARICCP_SUCCESS_STATE_CODE; //mod by xxl 2010-5-19 end ////test-------------------------- //strDec = "user"; //strDec.append(strUserName); //strDec.append("login succeed."); //myMemcpy(inner_RespFrame->header.strResuleDesc, strDec.c_str(), strlen(strDec.c_str())); //inner_RespFrame->iResultNum = 1; ////分配惟一的客户端号给用户 //string strVal = ""; //strVal = "ClientID = 2009"; //inner_RespFrame->m_vectTableValue.push_back(strVal); end: return iRes; }