/**
* @file CM_TCP.c
* @brief TCP通信的封装
* @author GT-BU
* @date 2022.03.29
* @version V1.1
* @copyright TCT
* @par 修改日志
* <table>
* <tr><th>Date        <th>Version  <th>Author     <th>Description
* <tr><td>2017.12.20  <td>V1.0     <td>MSCP项目组 <td>创建初始版本
* <tr><td>2021.02.01  <td>V1.1     <td>GT-BU      <td>TSCP项目集成、更新
* </table>
*/
#include "CM_TCP.h"
#include "CM_Memory.h"
#include "PFM_Cfg.h"
#include "PFM_Log.h"

#ifdef WIN32
#include <ws2tcpip.h> /* 组播 */
#endif
/** TCP服务已初始化标志 */
static CM_BOOL s_TCP_Initialized = CM_FALSE;

/** TCP消息结构体，线程安全 */
static STRU_TCP_MSG Tcp_Message[TCP_CONN_MAX];

static ENUM_CM_RETURN CM_TCP_Is_Read_Ready(IN CM_SOCKET sock);
static ENUM_CM_RETURN CM_TCP_Is_Write_Ready(IN CM_SOCKET sock);
/**
* @brief 初始化TCP服务
* @details 仅需初始化一次
*/
ENUM_CM_RETURN CM_TCP_Init(void)
{
    /*- 变量初始化 */
	CM_UINT16 Idex = 0u; 				 /* 临时变量 */
    ENUM_CM_RETURN rt = ENUM_CM_FALSE; /* 函数返回值 */

    /*- 初始化socket服务 */
    rt = CM_Socket_Init();

    /*- 是否车初始化成功 */
    if (ENUM_CM_TRUE == rt)
    {
    	/*- 初始化TCP消息结构体 */
    	(void)CM_Memset((void*)(&Tcp_Message[0]), (CM_UINT8)0U, (size_t)(sizeof(Tcp_Message)), (size_t)(sizeof(Tcp_Message)));
		for(Idex = 0u; Idex < TCP_CONN_MAX; Idex++)
		{
			rt = CM_Mutex_Init(&Tcp_Message[Idex].mutex);
			CM_NM_ASSERT(ENUM_CM_TRUE == rt, TCP_MODE,DARK_FAULT_CODE_FUN_ORDER_1,TSCP_DARK_ASSERT_1);
		}
        /*- TCP初始化成功 */
        s_TCP_Initialized = CM_TRUE;
    }
    else
	{
		/*- 无处理 */
	}

    /*- 返回初始化结果 */
    return rt;
}

/**
* @brief TCP套接字相关信息插入或更新
* @param tcpId tcpid用以映射，不能为0
* @param TcpSock 套接字，不能为0
* @param TcpState 套接字状态，不能为0
* @param TcpServerIp 服务端IP地址，不能为0
* @param TcpServerPort 服务端端口号，不能为0
* @preturn 插入结果
* - ENUM_CM_TRUE 查询成功
* - ENUM_CM_FALSE 查询失败
*/
ENUM_CM_RETURN CM_TCP_MsgIstOrUpd(IN CM_UINT16 tcpId, IN CM_SOCKET TcpSock, IN CM_UINT32 TcpState, IN CM_UINT32 TcpServerIp, IN CM_UINT16 TcpServerPort)
{
    /*- 变量初始化 */
    ENUM_CM_RETURN rt = ENUM_CM_FALSE; /* 函数返回值 */
	CM_UINT16 Idex = 0u;                  /* 临时变量 */

    /*- 是否TCP消息结构初始化成功并且参数有效*/
    if ((CM_TRUE == s_TCP_Initialized) && (0u != tcpId) && (0u != TcpState) && (0 != TcpSock) && (0u != TcpServerIp) && (0u != TcpServerPort))
    {
    	for(Idex = 0u; Idex < TCP_CONN_MAX; Idex++)
    	{
    		/*- 上锁 */
    		(void)CM_Mutex_Lock(Tcp_Message[Idex].mutex);
			
			/*- 第一次创建时判断TcpId为0就插入数据*/
			if(0u == Tcp_Message[Idex].TcpId)
			{
				Tcp_Message[Idex].TcpId = tcpId;
				Tcp_Message[Idex].TcpSock = TcpSock;
				Tcp_Message[Idex].TcpState = TcpState;
				Tcp_Message[Idex].TcpServerIp= TcpServerIp;
				Tcp_Message[Idex].TcpServerPort = TcpServerPort;

				/*- 释放锁 */
				(void)CM_Mutex_Unlock(Tcp_Message[Idex].mutex);
				rt = ENUM_CM_TRUE;
				/*- 跳出 */
				break;
			}
			else if(tcpId == Tcp_Message[Idex].TcpId)
			{
				/*- 判断TcpId相等则更新数据，不需要更新TcpId、TcpServerIp、TcpServerPort*/
				Tcp_Message[Idex].TcpSock = TcpSock;
				Tcp_Message[Idex].TcpState = TcpState;

				/*- 释放锁 */
				(void)CM_Mutex_Unlock(Tcp_Message[Idex].mutex);
				rt = ENUM_CM_TRUE;
				/*- 跳出 */
				break;
			}
			else
			{
				/*- 释放锁 */
				(void)CM_Mutex_Unlock(Tcp_Message[Idex].mutex);

				if (Idex == TCP_CONN_MAX - 1u)
				{
					/*日志记录*/
					MSCP_LOG_MSG("ERROR : Tcp_Message Is Full, More Than 9 Element.\n");
				}
				else
				{
					
				}
			}
		}
		
    }
    else
	{
		/*- 无处理 */
	}

    /*- 返回初始化结果 */
    return rt;
}

/**
* @brief TCP套接字相关信息更新
* @param tcpId tcpid用以映射，不能为0
* @param TcpState 套接字状态，不能为0
* @preturn 插入结果
* - ENUM_CM_TRUE 查询成功
* - ENUM_CM_FALSE 查询失败
*/
ENUM_CM_RETURN CM_TCP_Msgstate_Update(IN CM_UINT16 tcpId, IN CM_UINT32 TcpState)
{
    /*- 变量初始化 */
    ENUM_CM_RETURN rt = ENUM_CM_FALSE; /* 函数返回值 */
	CM_UINT16 Idex = 0u;                  /* 临时变量 */

    /*- 是否TCP消息结构初始化成功并且参数有效*/
    if ((CM_TRUE == s_TCP_Initialized) && (0u != tcpId))
    {
    	for(Idex = 0u; Idex < TCP_CONN_MAX; Idex++)
    	{
    	    /*- 上锁 */
    		(void)CM_Mutex_Lock(Tcp_Message[Idex].mutex);
			
			/*- 判断TcpId相等则更新状态 */
			if(tcpId == Tcp_Message[Idex].TcpId)
			{
				Tcp_Message[Idex].TcpState = TcpState;

				/*- 释放锁 */
				(void)CM_Mutex_Unlock(Tcp_Message[Idex].mutex);
				rt = ENUM_CM_TRUE;
				/*- 跳出 */
				break;
			}
			else
			{
				/*- 释放锁 */
				(void)CM_Mutex_Unlock(Tcp_Message[Idex].mutex);
				if (Idex == TCP_CONN_MAX - 1u)
				{
					/*日志记录*/
					MSCP_LOG_MSG("ERROR : TcpId =%d, Query Tcp_Message Failed, Not Found Tcpid.\n",tcpId);
				}
				else
				{
					
				}
			}
		}
    }
    else
	{
		/*- 无处理 */
	}

    /*- 返回初始化结果 */
    return rt;
}

/**
* @brief TCP套接字查询
* @param tcpId tcpid用以映射，不能为0
* @param pTcpState TCP状态
* @preturn 查询结果
* - ENUM_CM_TRUE 查询成功
* - ENUM_CM_FALSE 查询失败
*/
ENUM_CM_RETURN CM_TCP_Msgstate_Query(IN CM_UINT16 tcpId, INOUT CM_SOCKET *pTcpSock,INOUT CM_UINT32 *pTcpState,INOUT CM_UINT32 *pTcpServerIp,INOUT CM_UINT16 *pTcpServerPort )
{
    /*- 变量初始化 */
    ENUM_CM_RETURN rt = ENUM_CM_FALSE; /* 函数返回值 */
	CM_UINT16 Idex = 0u;                  /* 临时变量 */

    /*- 是否TCP消息结构初始化成功 */
    if ((CM_TRUE == s_TCP_Initialized) && (0u != tcpId))
    {
    	/*- 遍历Tcp消息结构体查询 */
		for(Idex = 0u; Idex < TCP_CONN_MAX; Idex++)
		{
			/*- 上锁 */
			(void)CM_Mutex_Lock(Tcp_Message[Idex].mutex);
			if(tcpId == Tcp_Message[Idex].TcpId)
			{
				*pTcpSock = Tcp_Message[Idex].TcpSock;
				(*pTcpState) = Tcp_Message[Idex].TcpState;
				(*pTcpServerIp) = Tcp_Message[Idex].TcpServerIp;
				(*pTcpServerPort )= Tcp_Message[Idex].TcpServerPort;
				
				/*- 释放锁 */
				(void)CM_Mutex_Unlock(Tcp_Message[Idex].mutex);
				rt = ENUM_CM_TRUE;
				/*- 跳出 */
				break;
			}
			else
			{
				/*- 释放锁 */
				(void)CM_Mutex_Unlock(Tcp_Message[Idex].mutex);
				if (Idex == TCP_CONN_MAX - 1u )
				{
					/*日志记录*/
					MSCP_LOG_MSG("ERROR : TcpId =%d, Query Tcp_Message Failed, Not Found Tcpid.\n",tcpId);
				}
				else
				{
					
				}
			}
		}
		
    }
    else
	{
		/*- 无处理 */
	}

    /*- 返回初始化结果 */
    return rt;
}

/**
* @brief socket是否可读
* @param sock soket
* @preturn 可读状态
* - ENUM_CM_TRUE 可读
* - ENUM_CM_FALSE 不可读
*/
static ENUM_CM_RETURN CM_TCP_Is_Read_Ready(IN CM_SOCKET sock)
{
    /*- 变量初始化 */
    CM_INT32 sFd = 0;                    /* 文件描述符 */
    CM_INT32 sFlag = 0;                  /* 临时变量 */
    struct timeval timeover1 = { 0, 0 }; /* 时间 */
    fd_set readok;                       /* 临时变量 */
    ENUM_CM_RETURN rt = ENUM_CM_FALSE;   /* 函数返回值 */
    /*- TCP服务是否已经初始化 */
    if (CM_TRUE == s_TCP_Initialized)
    {
        /*- select查询sock的读状态 */
        (void)CM_Memset((void*) &readok, (CM_UINT8)0U, (size_t)(sizeof(fd_set)), (size_t)(sizeof(fd_set)));
        timeover1.tv_sec = 0;

        timeover1.tv_usec = 0;

        FD_ZERO(&readok);
        FD_SET(sock, &readok);

        sFd = (CM_INT32)select((sock + 1), &readok, NULL, NULL, &timeover1);

        /*- @alias 判断sock是否可读*/
        if (sFd > 0)
        {
        	sFlag = FD_ISSET(sock, &readok);
            if (0 != sFlag)
            {
                rt = ENUM_CM_TRUE;
            }
            else
            {
                rt = ENUM_CM_FALSE;
            }
        }
        else
        {
            rt = ENUM_CM_FALSE;
        }
    }
    else
	{
		/*- 无处理 */
	}
    /*- 返回sock的可读状态 */
    return rt;
}

/**
* @brief socket是否可写
* @param sock soket
* @preturn 可写状态
* - ENUM_CM_TRUE 可写
* - ENUM_CM_FALSE 不可写
*/
static ENUM_CM_RETURN CM_TCP_Is_Write_Ready(IN CM_SOCKET sock)
{
    /*- 变量初始化 */
    CM_INT32 sFd = 0;                    /* 文件描述符 */
    CM_INT32 sFlag = 0;                  /* 临时变量 */
    struct timeval timeover1 = { 0, 0 }; /* 时间 */
    fd_set writeok;                      /* 临时变量 */
    ENUM_CM_RETURN rt = ENUM_CM_FALSE;   /* 函数返回值 */

    /*- TCP服务是否已经初始化 */
    if (CM_TRUE == s_TCP_Initialized)
    {
        /*- select查询sock的写状态 */
        (void)CM_Memset((void*) &writeok, (CM_UINT8)0U, (size_t)(sizeof(fd_set)), (size_t)(sizeof(fd_set)));
        timeover1.tv_sec = 0;
        timeover1.tv_usec = 0;
        FD_ZERO(&writeok);
        FD_SET(sock, &writeok);

        sFd = (CM_INT32)select((CM_INT32)(sock + 1), NULL, &writeok, NULL, &timeover1);

        /*- @alias 判断sock是否可写 */
        if (sFd > 0)
        {
        	sFlag = FD_ISSET(sock, &writeok);
            if (0 != sFlag)
            {
                rt = ENUM_CM_TRUE;
            }
            else
            {
                rt = ENUM_CM_FALSE;
            }
        }
        else
        {
            rt = ENUM_CM_FALSE;
        }
    }
    else
	{
		/*- 无处理 */
	}
    /*- 返回sock的可写状态 */
    return rt;
}

/**
* @brief TCP套接字选项设置
* @param pSock TCP套接字
* @preturn 设置结果
* - ENUM_CM_TRUE 设置成功
* - ENUM_CM_FALSE 设置失败
*/
ENUM_CM_RETURN CM_TCP_SetSockOpt(IN CM_SOCKET *pSock)
{
	CM_INT32 arg = 1;
	struct linger linger_opt;
	CM_INT32 ret = 0;                 /* 临时结果 */
	ENUM_CM_RETURN rt = ENUM_CM_FALSE; /* 函数返回值 */
	
	if(0 > *pSock)
	{
		rt = ENUM_CM_FALSE;
	}
	else
	{
		/*- 设置非阻塞 */
		arg = 1;
#ifdef WIN32
		ret = ioctlsocket(*pSock, (long)FIONBIO, (unsigned long*)&arg);
#else/*Linux Vxworks常用PIOX标准*/
		ret = ioctl(*pSock, FIONBIO, &arg);
#endif
		if (0 != ret)
		{
			/*- 设置非阻塞失败 */
			rt = ENUM_CM_FALSE;
		}
		else
		{
			/*- 关闭nagle算法,有数据立即发送 */
			arg = 1;
			ret = setsockopt(*pSock, IPPROTO_TCP, TCP_NODELAY, (char *)&arg, sizeof(arg));
			if (0 != ret)
			{
				/*- 关闭nagle算法失败 */
				rt = ENUM_CM_FALSE;
			}
			else
			{
				/*- set linger opt 在close时立即实施可靠关断,丢弃协议栈中未发出的数据 */
				linger_opt.l_onoff = 1;
   				linger_opt.l_linger = 0;
				ret = setsockopt(*pSock, SOL_SOCKET, SO_LINGER, (char *)&linger_opt, sizeof(linger_opt));
				if (0 != ret)
				{
					/*- 设置失败 */
					rt = ENUM_CM_FALSE;
				}
				else
				{
					/*- 所有设置成功 */
					rt = ENUM_CM_TRUE;
#if 1
					/*- 允许socket地址重用 */
					arg = 1;
					ret = setsockopt(*pSock, SOL_SOCKET , SO_REUSEADDR, (char *)&arg, sizeof(arg));
					if (0 != ret)
					{
						/*- 设置失败 */
						rt = ENUM_CM_FALSE;
					}
					else
                    {
#if QNX
						/*- 允许socket端口重用 */
						arg = 1;
						ret = setsockopt(*pSock, SOL_SOCKET , SO_REUSEPORT, (char *)&arg, sizeof(arg));
						if (0 != ret)
						{
							/*- 设置失败 */
							rt = ENUM_CM_FALSE;
						}
						else
						{						
							/*- 所有设置成功 */
							rt = ENUM_CM_TRUE;
						}
#endif
					}

#endif
				}
			}
		}
	}
	return rt;
}

/**
* @brief 宕机情况下，关闭所有TCP连接
* @return 关闭结果
* - ENUM_CM_TRUE 成功
* - ENUM_CM_FALSE 失败
*/
ENUM_CM_RETURN CM_TCP_Socket_Close_shutdown(void)
{
    /*- 变量初始化 */
	CM_UINT16 Idex = 0u;                  /* 临时变量 */
    ENUM_CM_RETURN rt = ENUM_CM_FALSE; /* 函数返回值 */     

    /*- 是否TCP服务未初始化 */
    if ((CM_TRUE != s_TCP_Initialized))
    {
        /*- 关闭失败 */
        rt = ENUM_CM_FALSE;
    }
    else
    {
		
    	for(Idex = 0u; Idex < TCP_CONN_MAX; Idex++)
		{
		    /*- 上锁 */
    		(void)CM_Mutex_Lock(Tcp_Message[Idex].mutex);
			
			if(0u != Tcp_Message[Idex].TcpId)
			{
				/* 关闭连接的读和写 */
				(void)shutdown(Tcp_Message[Idex].TcpSock,2);
				(void)close(Tcp_Message[Idex].TcpSock);

				/*- 释放锁 */
				(void)CM_Mutex_Unlock(Tcp_Message[Idex].mutex);
				
				/*- 关闭成功同步Tcp消息结构体成功 */
				rt = ENUM_CM_TRUE;	
				/*- 跳出 */
				break;
			}
			else
			{
				/*- 释放锁 */
				(void)CM_Mutex_Unlock(Tcp_Message[Idex].mutex);
			}
		}

    }
    /*- 返回创建结果 */
    return rt;
}

/**
* @brief 关闭TCP socket，并且更新Tcp_Message结构信息
* @param tcpId tcpid用以映射，不能为0
* @param TcpState Tcp状态标志
* @return 关闭结果
* - ENUM_CM_TRUE 成功
* - ENUM_CM_FALSE 失败
*/
ENUM_CM_RETURN CM_TCP_Socket_Close(IN CM_UINT16 tcpId, IN CM_UINT32 TcpState)
{
    /*- 变量初始化 */
	CM_UINT16 Idex = 0u;                  /* 临时变量 */
    ENUM_CM_RETURN rt = ENUM_CM_FALSE; /* 函数返回值 */     

    /*- 是否TCP服务未初始化或输入非法 */
    if ((CM_TRUE != s_TCP_Initialized) || (0u >= tcpId))
    {
        /*- 关闭失败 */
        rt = ENUM_CM_FALSE;
    }
    else
    {
		
    	for(Idex = 0u; Idex < TCP_CONN_MAX; Idex++)
		{
		    /*- 上锁 */
    		(void)CM_Mutex_Lock(Tcp_Message[Idex].mutex);
			
			if(tcpId == Tcp_Message[Idex].TcpId)
			{
				/* 关闭连接的读和写 */
				(void)shutdown(Tcp_Message[Idex].TcpSock,2);
				(void)close(Tcp_Message[Idex].TcpSock);
				Tcp_Message[Idex].TcpSock=0;
				Tcp_Message[Idex].TcpState = TcpState;

				/*- 释放锁 */
				(void)CM_Mutex_Unlock(Tcp_Message[Idex].mutex);
				
				/*- 关闭成功同步Tcp消息结构体成功 */
				rt = ENUM_CM_TRUE;	
				/*- 跳出 */
				break;
			}
			else
			{
				/*- 释放锁 */
				(void)CM_Mutex_Unlock(Tcp_Message[Idex].mutex);
				if (Idex == TCP_CONN_MAX -1u)
				{
					/*日志记录*/
					MSCP_LOG_MSG("ERROR : TcpId =%d, Query Tcp_Message Failed, Not Found Tcpid.\n",tcpId);
				}
				else
				{
					
				}
			}
		}

    }
    /*- 返回创建结果 */
    return rt;
}

/**
* @brief 创建TCP socket
* @param pSock socket指针
* @param ServeraddrIP 服务端IP地址
* @param ServerPort 服务端端口号
* @param tcpId tcpid用以映射，不能为0
* @return 创建结果
* - ENUM_CM_TRUE 创建成功
* - ENUM_CM_FALSE 创建失败
*/
ENUM_CM_RETURN CM_TCP_Socket_Create(INOUT CM_SOCKET *pSock, IN CM_UINT32 ClientaddrIP, IN CM_UINT16 ClientPort,IN CM_UINT16 tcpId , IN CM_UINT32 ServeraddrIP, IN CM_UINT16 ServerPort)
{
    /*- 变量初始化 */
    CM_SOCKADDR_T addrHost;           /* 主机地址 */
    CM_INT32 ret = 0;                 /* 临时结果 */
    ENUM_CM_RETURN rt = ENUM_CM_FALSE; /* 函数返回值 */     

    /*- 是否TCP服务未初始化或输入非法 */
    if ((CM_TRUE != s_TCP_Initialized) || (NULL == pSock) || (0u == tcpId))
    {
        /*- 创建失败 */
        rt = ENUM_CM_FALSE;
    }
    else
    {
        /*- 创建TCP socket*/
        (void)CM_Memset((void*) &addrHost, (CM_UINT8)0U, (size_t)(sizeof(CM_SOCKADDR_T)), (size_t)(sizeof(CM_SOCKADDR_T)));
        rt = CM_Socket_Create(pSock, CM_FALSE);
        /*- 创建socket是否成功 */
        if (ENUM_CM_TRUE == rt)
        {
        	/*- 设置套接字选项 */
        	ret = CM_TCP_SetSockOpt(pSock);

            /*- 设置socket的阻塞模式是否成功 */
            if (ENUM_CM_TRUE == ret)
            {
                /*- 绑定IP端口 */
	        	(void)CM_Memset((void*) &addrHost, (CM_UINT8)0U, (size_t)(sizeof(CM_SOCKADDR_T)), (size_t)(sizeof(CM_SOCKADDR_T)));
	            addrHost.sin_family = (CM_UINT16)AF_INET;             
	            addrHost.sin_port = htons(ClientPort);
	            addrHost.sin_addr.s_addr = ClientaddrIP;
	            ret = (CM_INT32)bind(*pSock, (CM_SOCKADDR*) &addrHost, (unsigned int)sizeof(CM_SOCKADDR));
				if (-1 == ret)
				{
					(void)MSCP_LOG_MSG("Tcp bind errno = %d, %s\n", errno,strerror(errno));
					rt = ENUM_CM_FALSE;
				}
				else
				{
	            	ret = CM_TCP_MsgIstOrUpd(tcpId,(*pSock),ENUM_CM_NOCONN,ServeraddrIP,ServerPort);
					if (ret == ENUM_CM_TRUE)
					{
						/*- 同步Tcp消息结构体成功 */
		                rt = ENUM_CM_TRUE; 	
					}
					else
					{
						/*- 关闭套接字 */
						(void)close(*pSock);
						
		                /*- 同步Tcp消息结构体失败 */
		                rt = ENUM_CM_FALSE; 						
					}					
				}
            }

            else
            {
              	/*- 关闭套接字 */
            	(void)close(*pSock);
				
				/*- 创建失败 */
       	 		rt = ENUM_CM_FALSE;
            }
        }
        else
		{
			/*- 创建失败 */
        	rt = ENUM_CM_FALSE;
		}
    }
    /*- 返回创建结果 */
    return rt;
}

/**
* @brief TCP建立连接
* @param tcpId tcpid用以映射，不能为0
* @param time_out 连接超时时间
* @return 连接结果
* - ENUM_CM_TRUE 成功
* - ENUM_CM_FALSE 失败
*/
ENUM_CM_RETURN CM_TCP_Socket_Connect(IN CM_UINT16 tcpId, IN CM_UINT32 time_out)
{
    /*- 变量初始化 */
    CM_INT32 ret = 0;                 /* 临时结果 */
	CM_SOCKET tcpsock = -1;			/* 临时变量 */
	CM_UINT32 ServeraddrIP = 0u;			/* 临时变量 */
	CM_UINT16 ServerPort = 0u;			/* 临时变量 */
	CM_UINT32 TcpState = 0u;			/* 临时变量 */
	CM_SOCKADDR_T addrServer;           /* 服务端地址信息 */
	CM_CHAR addrServerTmp[INET_ADDRSTRLEN];/*地址信息buff*/
	struct timeval select_Time_Out;/* 设置超时 */
	fd_set write_Set = {0};/* 写集合 */
    ENUM_CM_RETURN rt = ENUM_CM_FALSE; /* 函数返回值 */     

    /*- 是否TCP服务未初始化或输入非法 */
    if ((CM_TRUE != s_TCP_Initialized) || (0u >= tcpId))
    {
        /*- 关闭失败 */
        rt = ENUM_CM_FALSE;
    }
    else
    {

    	ret = CM_TCP_Msgstate_Query(tcpId, &tcpsock,&TcpState, &ServeraddrIP, &ServerPort);
		if (ENUM_CM_TRUE == ret)
		{
			/*- 判断状态为已创建，未连接则连接 */
			if ((CM_UINT32)ENUM_CM_NOCONN == TcpState)
			{
				/* 填充服务端地址信息 */
				addrServer.sin_family = AF_INET;
				addrServer.sin_addr.s_addr = ServeraddrIP;
				addrServer.sin_port = htons(ServerPort);
				
				/* 建立连接 */
				if (0 == connect(tcpsock, (CM_SOCKADDR*) &addrServer, sizeof(CM_SOCKADDR_T)))
				{
					/* 建立连接立即成功 */
					/* 转换服务端ip地址 */	
					if (NULL != inet_ntop(AF_INET, &addrServer.sin_addr, addrServerTmp, (CM_UINT32)INET_ADDRSTRLEN))
					{
						/*日志记录*/
						MSCP_LOG_MSG("connect %s port %u succeed immediately.\n",addrServerTmp, ntohs(addrServer.sin_port));
					}
					else
					{			
						/*日志记录*/
						MSCP_LOG_MSG("Couldn't convert Server address to string.\n");
					}
					
					/* 更新套接字状态为已创建并且连接成功 */
					ret = CM_TCP_Msgstate_Update(tcpId, ENUM_CM_CONNECTED);

					if (ENUM_CM_TRUE == ret)
					{
						 /*- 连接成功 */
						rt = ENUM_CM_TRUE;						
					}
					else
					{
						(void)CM_TCP_Socket_Close(tcpId,ENUM_CM_CONNFAIL);
					}			
				}
				else if((errno == EWOULDBLOCK) || (errno == EINPROGRESS) || (errno == EINTR))
				{
					/* 延时判断连接状态 */
				
					/* 设置超时时间 */
					if (time_out >= 1000U)
					{
						select_Time_Out.tv_sec	= time_out / 1000U;
						select_Time_Out.tv_usec = (time_out % 1000U) * 1000U;
					}
					else
					{
						select_Time_Out.tv_sec	= 0;
						select_Time_Out.tv_usec = time_out * 1000U;
					}
					
					FD_ZERO(&write_Set);
					FD_SET(tcpsock, &write_Set);
					ret = select(tcpsock + 1, NULL, &write_Set, NULL, &select_Time_Out);
					if (-1==ret)
					{
						/*日志记录*/
						MSCP_LOG_MSG("select error!\n");
						(void)CM_TCP_Socket_Close(tcpId,ENUM_CM_CONNFAIL);
					}
					else if(0==ret)
					{
						/*日志记录*/
						MSCP_LOG_MSG("connect time out! The network cable may not be connected or the service host may not be started!\n");
						(void)CM_TCP_Socket_Close(tcpId,ENUM_CM_CONNFAIL);
					}
					else
					{
						if (0 != FD_ISSET(tcpsock, &write_Set))
						{							
							/* 再次连接，如果连接失败且错误码为EISCONN说明已经连接成功 */
							ret = connect(tcpsock, (CM_SOCKADDR*) &addrServer, sizeof(CM_SOCKADDR_T));
							if (-1 == ret)
							{
								if (errno == EISCONN)
								{
									/*日志记录*/
									MSCP_LOG_MSG("connect finished.\n");
									/* 转换服务端ip地址 */	
									if (NULL != inet_ntop(AF_INET, &addrServer.sin_addr, addrServerTmp, INET_ADDRSTRLEN))
									{
										/*日志记录*/
										MSCP_LOG_MSG("connect %s port %u succeed.\n",addrServerTmp, ntohs(addrServer.sin_port));
									}
									else
									{			
										/*日志记录*/
										MSCP_LOG_MSG("Couldn't convert Server address to string.\n");
									}
									
									/* 更新套接字状态为已创建并且连接成功 */
									ret = CM_TCP_Msgstate_Update(tcpId, ENUM_CM_CONNECTED);
									
									if (ENUM_CM_TRUE == ret)
									{
										 /*- 连接成功 */
										rt = ENUM_CM_TRUE;						
									}
									else
									{
										(void)CM_TCP_Socket_Close(tcpId,ENUM_CM_CONNFAIL);
									}

				
								}
								else
								{
									/*日志记录*/
									MSCP_LOG_MSG("connect failed. errno = %d, %s.\n",errno,strerror(errno));
									
									/* 转换服务端ip地址 */	
									if (NULL != inet_ntop(AF_INET, &addrServer.sin_addr, addrServerTmp, INET_ADDRSTRLEN))
									{
										/*日志记录*/
										MSCP_LOG_MSG("connect %s port %u failed.the server process may not be started!\n",addrServerTmp, ntohs(addrServer.sin_port));
									}
									else
									{			
										/*日志记录*/
										MSCP_LOG_MSG("Couldn't convert Server address to string.\n");
									}
									(void)CM_TCP_Socket_Close(tcpId,ENUM_CM_CONNFAIL);
								}
							}
							else
							{
								/*-理论上不可达 */
							}
						}
						else
						{
				
						}
					}
				}
				else
				{
					/* 建立连接失败 */
					if (NULL != inet_ntop(AF_INET, &addrServer.sin_addr, addrServerTmp, INET_ADDRSTRLEN))
					{
						/*日志记录*/
						MSCP_LOG_MSG("connect %s port %u failed.\n",addrServerTmp, ntohs(addrServer.sin_port));
					}
					else
					{			
						/*日志记录*/
						MSCP_LOG_MSG("Couldn't convert Server address to string.\n");
					}	
					(void)CM_TCP_Socket_Close(tcpId,ENUM_CM_CONNFAIL);
				}

			}
			else
			{
				/*日志记录*/
				MSCP_LOG_MSG("ERROR : TcpState =%d, Not Equal ENUM_CM_NOCONN.\n",TcpState);
			}

		}
		else
		{
			/*- 无处理 */
		}
    }
    /*- 返回连接结果 */
    return rt;
}

/**
* @brief TCP发送
* @param tcpId tcpid用以映射，不能为0
* @param pBuf 发送报文指针
* @param bufSize 发送报文长度
* @return 发送结果
* - ENUM_CM_TRUE 成功
* - ENUM_CM_FALSE 失败
*/
ENUM_CM_RETURN CM_TCP_Send_Msg(IN CM_UINT16 tcpId, IN const CM_UINT8 pBuf[], IN CM_INT32 bufSize)
{
#if QNX
    /*- 变量初始化 */
    CM_INT32 ret = 0;                  /* 函数返回值 */
    ENUM_CM_RETURN rt = ENUM_CM_FALSE;  /* 函数返回值 */
	CM_SOCKET tcpsock = -1;			/* 临时变量 */
	CM_UINT32 ServeraddrIP = 0u;			/* 临时变量 */
	CM_UINT16 ServerPort = 0u;			/* 临时变量 */
	CM_UINT32 TcpState = 0u;			/* 临时变量 */
	CM_INT32 leftszie = 0;	/* 临时变量 */
#ifdef QNX
	ssize_t sendszie = 0;	/* 临时变量 */
#else
	CM_UINT32 sendszie = 0;
#endif

	const CM_UINT8* ptr = NULL;	/* 临时变量 */


    /*- TCP协议是否已经初始化 */
    if ((CM_TRUE == s_TCP_Initialized) && (0u < tcpId) && (NULL != pBuf) && (0 < bufSize))
    {
    	ret = CM_TCP_Msgstate_Query(tcpId, &tcpsock, &TcpState, &ServeraddrIP, &ServerPort);
		if (ENUM_CM_TRUE == ret)
		{
			if ((CM_UINT32)ENUM_CM_CONNECTED == TcpState)
			{
				ptr = pBuf;
				leftszie = bufSize;
				while(0 < leftszie)
				{
					/*- TCP发送 */
					sendszie = send(tcpsock,ptr,bufSize,MSG_NOSIGNAL);
					if (((CM_SOCKET_ERROR) == sendszie) && (errno == EINTR))
					{
						/*- 处理EINTR错误，系统调用被中断再次尝试发送 */
						sendszie = 0;
					}
					else if(CM_SOCKET_ERROR == sendszie)
					{
						/*- 发送失败，关闭套接字，置套接字状态为已断开连接，待创建 */
						if (errno == EPIPE)
						{
							/*日志记录*/
							MSCP_LOG_MSG("Server Process Down. errno = %d, %s.\n", errno,strerror(errno));
						}
						else if ((errno == EWOULDBLOCK) ||(errno == EAGAIN))
						{
							/*日志记录*/
							MSCP_LOG_MSG("The Tcp Send Buf Queue Is Full. errno = %d, %s.\n", errno,strerror(errno));
						}
						else
						{
							/*日志记录*/
							MSCP_LOG_MSG("send failed. errno = %d, %s.\n", errno,strerror(errno));
						}
						
						(void)CM_TCP_Socket_Close(tcpId,ENUM_CM_CLOSED);
						
						/*- 跳出while循环 */
						break;
					}
					else
					{
						/*- 接着发送直到leftszie等于0 */
						leftszie = bufSize - (CM_INT32)sendszie;
						ptr += sendszie;
					}
				}

				/*- 发送成功 */
				if (0 == leftszie)
				{
					rt = ENUM_CM_TRUE;	
				}
				else
				{
					/*- 无处理 */
				}				
			}
			else
			{
				/*日志记录*/
				MSCP_LOG_MSG("ERROR : TcpState =%d, Not Equal ENUM_CM_CONNECTED.\n",TcpState);
			}
		}
		else
		{
			
		}
    }
    else
	{
		/*- 无处理 */
	}
    /*- 返回发送结果 */
    return rt;
#else
    return ENUM_CM_TRUE;
#endif
}

/**
* @brief TCP接收消息查找完整帧
* @param pBuf tcp消息Buf
* @param bufSize buf长度
* @param pFullFrameSize 完整帧长度
* @preturn 完整包结果
* - ENUM_CM_TRUE 有完整帧
* - ENUM_CM_FALSE 没有完整帧
*/
ENUM_CM_RETURN CM_TCP_Find_Full_Frame(IN CM_UINT8 pBuf[], IN CM_INT32 bufSize, INOUT CM_INT32 *pFullFrameSize)
{
    /*- 变量初始化 */
	CM_UINT16 Idex = 0u; 				 /* 临时变量 */
	CM_UINT16 count_LBkt = 0u; 				 /* 计数{ */
	CM_UINT16 count_LBkt_Fg = 0u; 				 /* 计数{ 找到标志*/
	CM_UINT16 count_RBkt = 0u; 				 /* 计数} */
	CM_UINT16 Flag = 0u; 				 /* 找到完整帧标志 */
    ENUM_CM_RETURN rt = ENUM_CM_FALSE; /* 函数返回值 */

	/*- 遍历数据 */
	for(Idex = 0u; Idex < (CM_UINT32)bufSize; Idex++)
	{
		if ('{' == pBuf[Idex])
		{
			count_LBkt++;
			count_LBkt_Fg++;
		}
		else if('}' == pBuf[Idex])
		{
			count_RBkt++;
		}
		else
		{
			/*- 无处理 */
		}

		/*- 如果左括号等于右括号并且值不为0，说明有完整帧 */
		if ((count_LBkt == count_RBkt) && (0u != count_LBkt))
		{
			/*- 计数重新置0，接着遍历 */
			count_LBkt = 0u;
			count_RBkt = 0u;

			/*- 完整帧长度等于索引下标加1 */
			(*pFullFrameSize) = Idex + 1U;
			Flag = 1u;
			rt = ENUM_CM_TRUE;
		}
		else
		{
			/*- 无处理 */
		}
	}

	if (0u == Flag)
	{
		*pFullFrameSize = 0;
	}
	else
	{
		/*- 无处理 */
	}
	
    /*- 返回初始化结果 */
    return rt;
}

/**
* @brief TCP接收
* @param tcpId tcpid用以映射，不能为0
* @param pBuf 接收报文指针
* @param bufSize 接收报文长度
* @return 收到报文长度
* - 正整数 收到的报文长度
* - 0 未收到报文
* - -1 接收异常
* - -2 参数检查不合法
*/
CM_INT32 CM_TCP_Recv_Msg(IN CM_UINT16 tcpId, INOUT CM_UINT8 pBuf[], IN CM_INT32 bufSize)
{
    /*- 变量初始化 */
#ifdef QNX
    ssize_t recvNum = 0; /* 接收长度 */
#else
	CM_UINT32 recvNum = 0;
#endif

	CM_INT32 recvNumFianl = 0; /* 最终接收长度 */
	CM_UINT8  recvBuftmp[CM_TCP_BUFERSIZE];
	CM_SOCKET tcpsock = -1;			/* 临时变量 */
	CM_UINT32 ServeraddrIP = 0u;			/* 临时变量 */
	CM_UINT16 ServerPort = 0u;			/* 临时变量 */
	CM_UINT32 TcpState = 0u;			/* 临时变量 */
	CM_INT32 bufSizetmp = 0;				/* 临时变量 */
	CM_INT32 ret = 0;                  /* 函数返回值 */
	ENUM_CM_RETURN ret_m = ENUM_CM_FALSE; /* memcpy函数返回值 */

    /*- 是否TCP协议未初始化或输入非法 */
    if ((CM_TRUE != s_TCP_Initialized) || (NULL == pBuf) || (0u >= tcpId))
    {
        recvNumFianl = -2;
    }
    else
    {        
    	ret = CM_TCP_Msgstate_Query(tcpId, &tcpsock, &TcpState, &ServeraddrIP, &ServerPort);
		if (ENUM_CM_TRUE == ret)
		{
			if ((CM_UINT32)ENUM_CM_CONNECTED == TcpState)
			{
				while( 1 )
				{
					/*- TCP接收 */
					recvNum = recv(tcpsock, recvBuftmp, sizeof(recvBuftmp), 0);
					if (0 == recvNum)
					{
						/*- 服务端断开连接 */
						/*日志记录*/
						MSCP_LOG_MSG("ERROR :Server Process Has DisConnected.\n");

						/*- 本端断开连接，关闭套接字，置套接字状态为已断开连接，待创建 */
						(void)CM_TCP_Socket_Close(tcpId,ENUM_CM_CLOSED);

						recvNumFianl = -1;
						/*- 跳出 */
						break;
					}
					else if((CM_SOCKET_ERROR == recvNum) && (errno == EINTR))
					{
						/*- 非阻塞的正常情况，系统调用被中断 */

						/*- 再次尝试接收 */

					}
					else if((CM_SOCKET_ERROR == recvNum) && ((errno == EWOULDBLOCK) ||(errno == EAGAIN)))
					{
						/*- 非阻塞的正常情况，没有数据到来 */

						recvNumFianl += 0;


						/*- 跳出while循环，下次接收 */
						break;
					}
					else if(CM_SOCKET_ERROR == recvNum)
					{
						/*- 接收失败，关闭套接字，置套接字状态为已断开连接，待创建 */
						/*日志记录*/
						MSCP_LOG_MSG("recv failed. errno = %d, %s.\n", errno,strerror(errno));
						
						(void)CM_TCP_Socket_Close(tcpId,ENUM_CM_CLOSED);
						
						recvNumFianl = -1;
						
						/*- 跳出while循环 */
						break;

					}
					else
					{
						/*- 接收成功，将数据拷贝到缓冲区中，可能有数据未收完继续接收 */
						ret_m = CM_Memcpy((void*)(pBuf +bufSizetmp), (CM_SIZE_T)(bufSize - bufSizetmp), (void*)(recvBuftmp), (CM_SIZE_T)recvNum);
						if (ENUM_CM_TRUE == ret_m)
						{
							bufSizetmp += recvNum;
							recvNumFianl = bufSizetmp;							
						}
						else
						{
							/*需要防护*/
							/*服务端异常，*/
							MSCP_LOG_MSG("ERROR :Server Process Is Unusual.Too many message recv!\n");

							/*- 本端断开连接，关闭套接字，置套接字状态为已断开连接，待创建 */
							(void)CM_TCP_Socket_Close(tcpId,ENUM_CM_CLOSED);

							recvNumFianl = -1;
							/*- 跳出 */
							break;
						}

					}
				}				
			}
			else
			{
				/*日志记录*/
				MSCP_LOG_MSG("ERROR : TcpState =%d, Not Equal ENUM_CM_CONNECTED.\n");
			}
		}
		else
		{
			/*- 无处理 */
		}

    }
	
    /*- 返回接收长度 */
    return recvNumFianl;
}
