socket_client_tcp

socket_client_tcp.h

#ifndef __SOCKET_CLIENT_TCP_H__
#define __SOCKET_CLIENT_TCP_H__

#ifdef __cplusplus
extern "C" {
#endif
#pragma pack(1)

#define SOCKET_STATUS ODVS_STATUS
#define SOCKET_ERROR  ODVS_ERROR
#define SOCKET_OK     ODVS_OK

#define SOCKET_BOOL   ODVS_BOOL
#define SOCKET_TRUE   ODVS_TRUE
#define SOCKET_FALSE  ODVS_FALSE

/*通过socket接收外部数据的等待超时时间*/
#define CLIENT_CONNECT_TIMEOUT_SEC   1  /*s*/
#define CLIENT_CONNECT_TIMEOUT_USEC  0  /*us*/
#define CLIENT_RECV_TIMEOUT_SEC      1  /*s*/
#define CLIENT_RECV_TIMEOUT_USEC     0  /*us*/
#define CLIENT_SEND_TIMEOUT_SEC      1  /*s*/
#define CLIENT_SEND_TIMEOUT_USEC     0  /*us*/

#define CLIENT_RECV_BUFF_SIZE 1024 /*1 k*/

typedef INT32 (* func)(BYTE *, WORD32);
typedef struct timeout
{
    TimeInfo Connect;
    TimeInfo Send;
    TimeInfo Recv; 
}ClientTimeout;
typedef enum status
{
    CLIENT_STOPPED       = 0, /*stopped*/
    CLIENT_INIT          = 1,/*initialized*/
    CLIENT_CONNECT       = 2,/*connect server*/
    CLIENT_RUNNING       = 3,
    CLIENT_CHANGE_SERVER = 4,/*connected server info changed,need to reconnect*/
}ClientStatus;
typedef struct client
{
    ClientStatus ClientSts;
    INT32 Sockfd;
    CHAR ServerIp[20];
    UINT32 ServerPort;
    ClientTimeout timeout;
    func  RecvHandler;
    CHAR  Buffer[CLIENT_RECV_BUFF_SIZE];
}SocketClientInfo;


/****************************extern functions************************/
extern void ChangeSocketServerInfo(CHAR *server, UINT32 port);
extern SOCKET_STATUS ModifyClientTimeout(TimeInfo send, TimeInfo recv);
extern void RegisterRecvHandler(func handler);
extern SOCKET_STATUS StartTcpClientMdl();
extern void StartClient();
extern void StopClient();

#pragma pack()
#ifdef __cplusplus
}
#endif
#endif

 

 

socket_client_tcp.c

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>

#include "comm_types_ex.h"
#include "comm_struct_ex.h"
#include "comm_utils_ex.h"
#include "comm_log_ex.h"
#include "import_wrapper_ex.h"
#include "socket_client_tcp.h"

SocketClientInfo g_stClient = 
{
    CLIENT_STOPPED, 
    SOCKET_ERROR, 
    "10.63.180.66", 
    2899, 
    { 
        {CLIENT_CONNECT_TIMEOUT_SEC,CLIENT_CONNECT_TIMEOUT_USEC},
        {CLIENT_SEND_TIMEOUT_SEC,CLIENT_SEND_TIMEOUT_USEC},
        {CLIENT_RECV_TIMEOUT_SEC,CLIENT_RECV_TIMEOUT_USEC}
    }, 
    NULL,
    {0}
};

SOCKET_STATUS CloseSocket()
{
    if(close(g_stClient.Sockfd))
    {
        DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "Error: Close socket failed");
        return SOCKET_ERROR;
    }
    g_stClient.Sockfd = -1;
    DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "Success: Client is closed!");
    return SOCKET_OK;
}
SOCKET_STATUS ClientCreateSocket()
{
    memset(g_stClient.Buffer, 0, CLIENT_RECV_BUFF_SIZE);
    
    /* 创建客户端套接字--IPv4协议,面向连接通信,TCP协议 */
    g_stClient.Sockfd= socket(PF_INET, SOCK_STREAM, 0);
    if (g_stClient.Sockfd < 0)
    {
        return SOCKET_ERROR;
    }
    return SOCKET_OK;
}
void NON_BLOCK()
{
    INT32 flag = 0;
    
    flag = fcntl(g_stClient.Sockfd, F_GETFL, NULL);
    fcntl(g_stClient.Sockfd, F_SETFL, flag | O_NONBLOCK);/* non-blocking mode */
}
void BLOCK()
{
    INT32 flag = 0;
    
    flag = fcntl(g_stClient.Sockfd, F_GETFL, NULL);
    fcntl(g_stClient.Sockfd, F_SETFL, flag & (~O_NONBLOCK));/*blocking mode*/
}
SOCKET_STATUS NonblockConnect()
{
    SOCKET_STATUS connRet = SOCKET_ERROR;
    SockAddrIn remoteAddr;
    
    if(g_stClient.Sockfd < 0)
    {
        DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "Error: Socket has not been created!");

        connRet = SOCKET_ERROR;
    }
    else
    {
        memset(&remoteAddr, 0, sizeof(remoteAddr));
        remoteAddr.sin_family      = AF_INET;
        remoteAddr.sin_addr.s_addr = inet_addr(g_stClient.ServerIp);
        remoteAddr.sin_port        = htons(g_stClient.ServerPort);

        connRet = connect(g_stClient.Sockfd, (SockAddr *)&(remoteAddr), sizeof(SockAddr));
        
        if(SOCKET_ERROR == connRet)
        {
            DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "Error: Connect server failed");
        }
    }
    
    return connRet;
}
SOCKET_BOOL CanSockWrite(fd_set *writeset)
{
    INT32 error = 0, ret = SOCKET_ERROR;
    INT32 len = sizeof(INT32);
    
    if(FD_ISSET(g_stClient.Sockfd, writeset))
    {
        if(getsockopt(g_stClient.Sockfd, SOL_SOCKET, SO_ERROR, &error, &len)<0)
        {
            ret = SOCKET_FALSE;
        }
        if(error == 0)
        {
            DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "Success: Connect server success");
            ret = SOCKET_TRUE;
        }
        else
        {
            DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "Error: Unexpect error in getsockopt");
            ret = SOCKET_FALSE;
        }
    }
    else
    {
        DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "Error: Connect failed");
        ret = SOCKET_FALSE;
    }
    return ret;
}
SOCKET_STATUS TestSockWriteable()
{
    SOCKET_BOOL ret;
    SOCKET_STATUS selecRet;
    fd_set writeset;
    TimeInfo timeout = g_stClient.timeout.Connect;
    
    FD_ZERO(&writeset);
    FD_SET(g_stClient.Sockfd, &writeset);
    selecRet = select(g_stClient.Sockfd+1, NULL, &writeset, NULL, &timeout);

    if(selecRet < 0)
    {
        DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "Error: Select failed");
        ret = SOCKET_FALSE;
    }
    else if(selecRet == 0)
    {
        DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "Error: Connect timeout");
        ret = SOCKET_FALSE;
    }
    else/* check if socket writeable*/
    {
        if(CanSockWrite(&writeset))
        {
            ret = SOCKET_TRUE;
        }
        else
        {
            ret = SOCKET_FALSE;
        }
    }
    return ret;
}
SOCKET_STATUS CheckConnStatus()
{
    SOCKET_STATUS ret = SOCKET_ERROR;
    
    if(errno != EINPROGRESS)/* 连接不在进行中,出现错误*/
    {
        DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "Error: Connect failed");

        if(errno == EISCONN)/*  关闭连着状态的服务 */
        {
            close(g_stClient.Sockfd);
            g_stClient.Sockfd = SOCKET_ERROR;
            g_stClient.ClientSts = CLIENT_INIT;
        }

        ret = SOCKET_ERROR;
    }
    else/* connection is under porgress */
    {
        if(TestSockWriteable())
        {
            ret = SOCKET_OK;
        }
        else
        {
            ret = SOCKET_ERROR;
        }
    }
    return ret;
}
/* 设置超时连接,连接超时返回错误 */
SOCKET_STATUS ClientConnectServer()
{
    SOCKET_STATUS ret = SOCKET_ERROR;
    
    NON_BLOCK();
    
    if(NonblockConnect() == SOCKET_ERROR)/* under process:非阻塞模式,返回值-1不表示错误 */
    {
        ret = CheckConnStatus();
    }
    else/* connect success */
    {
        DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "Success: Connect OK!");
        ret = SOCKET_OK;
    }
    
    BLOCK();

    return ret;
}
void ChangeSocketServerInfo(CHAR *pServer, UINT32 port)
{
    if(pServer != NULL && strcmp(pServer, g_stClient.ServerIp) != 0)
    {
        memcpy(g_stClient.ServerIp, pServer, strlen(pServer));
        g_stClient.ServerIp[strlen(pServer)] = '\0';
    }
    if(port != 0 && port != g_stClient.ServerPort)
    {
        g_stClient.ServerPort = port;
    }
    
    g_stClient.ClientSts = CLIENT_CHANGE_SERVER;
}

INT32 TcpClientSend(WORD32 *buf, WORD32 len)
{
    INT32 sendNum = 0;
    
    if(g_stClient.Sockfd < 0)
    {
        return SOCKET_ERROR;
    }
    sendNum = send(g_stClient.Sockfd, (CHAR *)buf, len, 0);
    if(sendNum < 0)
    {
        /* TO-DO:send failed */
    }
    return sendNum;
}

SOCKET_STATUS ClientRecv()
{
    INT32 recvNum = 0;
    
    if(g_stClient.Sockfd < 0)
    {
        return SOCKET_ERROR;
    }
    memset(g_stClient.Buffer, 0, CLIENT_RECV_BUFF_SIZE);
    recvNum = recv(g_stClient.Sockfd, g_stClient.Buffer, CLIENT_RECV_BUFF_SIZE, 0);

    return recvNum;
}

SOCKET_STATUS SetClientTimeout()
{
    SOCKET_STATUS ret;
    
    if(g_stClient.Sockfd < 0)
    {
        return SOCKET_ERROR;
    }

    ret = setsockopt(g_stClient.Sockfd, SOL_SOCKET, SO_RCVTIMEO, &g_stClient.timeout.Recv,sizeof(TimeInfo));
    ret = setsockopt(g_stClient.Sockfd, SOL_SOCKET, SO_SNDTIMEO, &g_stClient.timeout.Send,sizeof(TimeInfo));

    return ret;
}
SOCKET_STATUS ModifyClientTimeout(TimeInfo send, TimeInfo recv)
{
    SOCKET_STATUS ret;
    
    if(g_stClient.Sockfd < 0)
    {
        return SOCKET_ERROR;
    }
    g_stClient.timeout.Recv = recv;
    g_stClient.timeout.Send = send;
    ret = SetClientTimeout();
    
    return ret;
}
SOCKET_STATUS ClientRecvHandler(BYTE *data, INT32 len)
{
    if(NULL == data || NULL == g_stClient.RecvHandler)
    {
        return SOCKET_ERROR;
    }
    if(IsModLogOn(LOG_MDL_TCP_CLIENT))
    {
        DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "Client recv %d data", len);
        ShowHexData((WORD8 *)data, len);
    }
   
    return g_stClient.RecvHandler(data, len);
}
void StopClient()
{
    g_stClient.ClientSts = CLIENT_STOPPED;
}
void StartClient()
{
    g_stClient.ClientSts = CLIENT_RUNNING;
}
ClientStatus GetClientStatus()
{
    return g_stClient.ClientSts;
}
void RegisterRecvHandler(func handler)
{
    g_stClient.RecvHandler = handler;
}
SOCKET_STATUS ClientRecving()
{
    INT32 recvNum = 0;
    SOCKET_STATUS iRet = SOCKET_OK;
    
    recvNum = ClientRecv();

    if(recvNum < 0)
    {
        OdvsTaskDelay(100);
    }
    else if(recvNum == 0)/* connect is terminated */
    {
        iRet = SOCKET_ERROR;
        close(g_stClient.Sockfd);
        OdvsTaskDelay(100);
    }
    else if(recvNum > 0)
    {   
        ClientRecvHandler(g_stClient.Buffer, recvNum);
        OdvsTaskDelay(1);
    }
    
    return iRet;
}
SOCKET_STATUS CreateOkMoveNext(SOCKET_STATUS sts, INT32 delay)
{
    SOCKET_BOOL ret = SOCKET_TRUE;
    
    if(SOCKET_ERROR == sts)
    {
        OdvsTaskDelay(delay);
        ret = SOCKET_FALSE;
    }
    
    return ret;
}
SOCKET_STATUS ConnectOkMoveNext(SOCKET_STATUS sts, INT32 delay)
{
    SOCKET_BOOL ret = SOCKET_TRUE;
    
    if(SOCKET_ERROR == sts)
    {
        OdvsTaskDelay(delay);
        ret = SOCKET_FALSE;
    }
    else
    {   
        SetClientTimeout();
    }
    return ret;
}
SOCKET_STATUS RecvErrMoveNext(SOCKET_STATUS sts, INT32 delay)
{
    SOCKET_BOOL ret = SOCKET_TRUE;
    if(SOCKET_OK == sts)
    {
        OdvsTaskDelay(delay);
        ret = SOCKET_FALSE;
    }
    return ret;
}
SOCKET_STATUS ClientRun(INT32 arg1, INT32 arg2, INT32 arg3, INT32 arg4, INT32 arg5,
                       INT32 arg6, INT32 arg7, INT32 arg8, INT32 arg9, INT32 arg10)
{   
    INT32 iDefaultDelay = 100; /* 100 * 10ms */

    while(SOCKET_TRUE)
    {
        switch(g_stClient.ClientSts)
        {
            case CLIENT_INIT:
                if(CreateOkMoveNext(ClientCreateSocket(), iDefaultDelay))
                {
                    g_stClient.ClientSts = CLIENT_CONNECT;
                }
                break;
            case CLIENT_CONNECT:
                if(ConnectOkMoveNext(ClientConnectServer(), iDefaultDelay))
                {
                    g_stClient.ClientSts = CLIENT_RUNNING;
                }
                break;
            case CLIENT_RUNNING:
                if(RecvErrMoveNext(ClientRecving(), iDefaultDelay))
                {
                    g_stClient.ClientSts = CLIENT_INIT;
                }
                break;
            case CLIENT_CHANGE_SERVER:
                CloseSocket();
                g_stClient.ClientSts = CLIENT_INIT;
                break;
            case CLIENT_STOPPED:
                OdvsTaskDelay(200);
                break;
            default:
                OdvsTaskDelay(100);
                break;
                
        }
    }
}
SOCKET_STATUS StartupClientThread()
{
    return OdvsTaskSpawn("ClientTcp", 90, 0, 0x2000, (ODVS_FUNCPTR)ClientRun, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
SOCKET_STATUS StartTcpClientMdl()
{
    SOCKET_STATUS ret = SOCKET_ERROR;
    
    g_stClient.ClientSts = CLIENT_INIT;
    StartupClientThread();

    return ret;
}
/***********************HELP*******************/
void ShowClientInfoHelp()
{
    CHAR *sts[] = {"CLIENT_STOPPED", "CLIENT_INIT", "CLIENT_CONNECT","CLIENT_RUNNING", "CLIENT_CHANGE_SERVER"};

    printf("\n===============================================");
    printf("\n------------Client Information-----------------\n");
    printf("Client Status          : %s\n", sts[g_stClient.ClientSts]);
    printf("Client Socket FD       : %d\n", g_stClient.Sockfd);
    printf("Client Server ip       : %s\n", g_stClient.ServerIp);
    printf("Client Server port     : %d\n", g_stClient.ServerPort);
    printf("Client timeout connect : %ld\n", g_stClient.timeout.Connect.tv_sec);
    printf("Client timeout Send    : %ld\n", g_stClient.timeout.Send.tv_sec);
    printf("Client timeout Recv    : %ld\n", g_stClient.timeout.Recv.tv_sec);
    printf("Client recv buffer addr: %p\n", g_stClient.Buffer);
    printf("handler                : %p\n", g_stClient.RecvHandler);
    printf("===============================================\n");
}
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <ifaddrs.h> 
#include <fcntl.h>
#include <time.h>
#include <unistd.h>

#include "comm_types_ex.h"
#include "comm_struct_ex.h"
#include "comm_utils_ex.h"
#include "comm_log_ex.h"
#include "import_wrapper_ex.h"
#include "socket_ex.h"
#include "socket_client_tcp.h"
#include "layer_if_ex.h"
#include "cfg_ex.h"


WORD32 SOCKET_SND_DEBUG = 0;
SocketClientInfo g_stClient =
{
    CLIENT_STOPPED,
    SOCKET_ERROR,
    CFG_DEFAULT_TCP_IP,
    CFG_DEFAULT_TCP_PORT,
    {
        {CLIENT_CONNECT_TIMEOUT_SEC, CLIENT_CONNECT_TIMEOUT_USEC},
        {CLIENT_SEND_TIMEOUT_SEC, CLIENT_SEND_TIMEOUT_USEC},
        {CLIENT_RECV_TIMEOUT_SEC, CLIENT_RECV_TIMEOUT_USEC}
    },
    NULL,
    {0}, {0}
};

/* tcp server */
void SetConfigTcpServer(CHAR *pIp, WORD32 port)
{
    strcpy(g_stClient.ServerIp, pIp);
    g_stClient.ServerPort = port;
}

void GetTcpServerInfo(CHAR *pIp, WORD32 *pPort)
{
    strcpy(pIp, g_stClient.ServerIp);
    *pPort = g_stClient.ServerPort;
}

WORD32 GetTcpServerPort()
{
    return g_stClient.ServerPort;
}

INT32 GetGatewayAddr(CHAR *gateway)
{
    CHAR buff[256] = {0};
    INT32  nl = 0, fl = 0;
    InAddr gw;
    INT32  ref, use, metric;
    UINT32 flgs;
    ULONG  d,g,m;
    FILE  *fp = NULL;
    
    fp = fopen("/proc/net/route", "r");
    if (fp == NULL)
    {
        DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "Error: open /proc/net/route failed!");
        return SOCKET_ERROR;
    }
        
    while (fgets(buff, sizeof(buff), fp) != NULL) 
    {
        if (nl) 
        {
            fl = 0;
            while ((buff[fl] != ' ') && (buff[fl] != '\t') && (buff[fl] != '\0'))
            {
                fl++;
            }
            buff[fl] = 0;    /* interface */
            if (sscanf(buff+fl+1, "%lx%lx%x%d%d%d%lx", &d, &g, &flgs, &ref, &use, &metric, &m) != 7) 
            {
                fclose(fp);
                DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "Error: sscanf failed!");
                return SOCKET_ERROR;
            }
            gw.s_addr = g;  /* parse flags */
            if (d == 0)
            {
                strcpy(gateway, inet_ntoa(gw));
                DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC,  __FUNCTION__, __LINE__, "\ngateway: %s\n", gateway);
                fclose(fp);
                return SOCKET_OK;
            }                
        }
        nl++;
    }    

    fclose(fp);
    fp = NULL;
    
    DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "Error: fgets failed!");
    return SOCKET_ERROR;
}

INT32 GetMacAddr(INT32 sockfd, CHAR *ip, CHAR *mac) 
{
    WORD8  *pMac = NULL;
    ArpReq arpreq;  
    SockAddrIn *dstadd_in = NULL; 
    INT32  interfaceNum = 0;
    IfReq  buf[16] = {0};
    IfConf ifc;
    
    memset(&arpreq, 0, sizeof(ArpReq));  
    arpreq.arp_pa.sa_family = AF_INET;  
    arpreq.arp_ha.sa_family = AF_UNSPEC; 
    dstadd_in = (SockAddrIn *)&(arpreq.arp_pa);
    inet_pton(AF_INET, ip, &(dstadd_in->sin_addr));

    ifc.ifc_len = sizeof(buf);
    ifc.ifc_buf = (caddr_t)buf;
    if (!ioctl(sockfd, SIOCGIFCONF, (CHAR *)&ifc))
    {
        interfaceNum = ifc.ifc_len / sizeof(IfReq);
        while (interfaceNum-- > 0)
        {
            DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "\ndevice name: %s\n", buf[interfaceNum].ifr_name);
            strcpy(arpreq.arp_dev, buf[interfaceNum].ifr_name); 
            if (!ioctl(sockfd, SIOCGARP, &arpreq))
            {
                pMac = (WORD8 *)arpreq.arp_ha.sa_data;
                memcpy(mac, pMac, MAC_ADDRESS_LEN);
                #if 0
                sprintf(mac, "%02x-%02x-%02x-%02x-%02x-%02x",
                        pMac[0], pMac[1], pMac[2], pMac[3], pMac[4], pMac[5]);
                #endif
                DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, 
                        "\nMAC: %x-%x-%x-%x-%x-%x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
                return SOCKET_OK;
            }
            else
            {
                DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "Error: ioctl() SIOCGARP failed!");
            }
        }
    }
    else
    {
        DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "Error: ioctl() SIOCGIFCONF failed!");
    }

    return SOCKET_ERROR;  
} 

INT32 GetRouteMacAddr(INT32 sockfd, CHAR *mac)
{
    CHAR gateway[15] = {0};
    
    if (SOCKET_ERROR == GetGatewayAddr(gateway))
    {
        DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "Error: Get gateway addr failed!");
        return SOCKET_ERROR;
    }
    if (SOCKET_ERROR == GetMacAddr(sockfd, gateway, mac))
    {
        DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "Error: Get mac addr failed!");
        return SOCKET_ERROR;
    }
    
    return SOCKET_OK;
}

SOCKET_STATUS CloseSocket()
{
    if (close(g_stClient.Sockfd))
    {
        DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "Error: Close socket failed");
        return SOCKET_ERROR;
    }
    g_stClient.Sockfd = -1;
    DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "Success: Client is closed!");
    return SOCKET_OK;
}
SOCKET_STATUS ClientCreateSocket()
{
    memset(g_stClient.Buffer, 0, CLIENT_RECV_BUFF_SIZE);
    
    /* 创建客户端套接字--IPv4协议,面向连接通信,TCP协议 */
    g_stClient.Sockfd= socket(PF_INET, SOCK_STREAM, 0);
    if (g_stClient.Sockfd < 0)
    {
        return SOCKET_ERROR;
    }
    return SOCKET_OK;
}
void NON_BLOCK()
{
    INT32 flag = 0;
    
    flag = fcntl(g_stClient.Sockfd, F_GETFL, NULL);
    fcntl(g_stClient.Sockfd, F_SETFL, flag | O_NONBLOCK);/* non-blocking mode */
}
void BLOCK()
{
    INT32 flag = 0;
    
    flag = fcntl(g_stClient.Sockfd, F_GETFL, NULL);
    fcntl(g_stClient.Sockfd, F_SETFL, flag & (~O_NONBLOCK));/*blocking mode*/
}
SOCKET_STATUS NonblockConnect()
{
    SOCKET_STATUS connRet = SOCKET_ERROR;
    SockAddrIn remoteAddr;
    
    if(g_stClient.Sockfd < 0)
    {
        DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "Error: Socket has not been created!");

        connRet = SOCKET_ERROR;
    }
    else
    {
        memset(&remoteAddr, 0, sizeof(remoteAddr));
        remoteAddr.sin_family      = AF_INET;
        remoteAddr.sin_addr.s_addr = inet_addr(g_stClient.ServerIp);
        remoteAddr.sin_port        = htons(g_stClient.ServerPort);

        connRet = connect(g_stClient.Sockfd, (SockAddr *)&(remoteAddr), sizeof(SockAddr));
        
        if(SOCKET_ERROR == connRet)
        {
            DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_DETAIL, __FUNCTION__, __LINE__, "Error: Connect server failed");
        }
    }
    
    return connRet;
}
SOCKET_BOOL CanSockWrite(fd_set *writeset)
{
    INT32 error = 0, ret = SOCKET_ERROR;
    INT32 len = sizeof(INT32);
    
    if(FD_ISSET(g_stClient.Sockfd, writeset))
    {
        if(getsockopt(g_stClient.Sockfd, SOL_SOCKET, SO_ERROR, &error, &len)<0)
        {
            ret = SOCKET_FALSE;
        }
        if(error == 0)
        {
            DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "Success: Connect server success");
            ret = SOCKET_TRUE;
        }
        else
        {
            DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_DETAIL, __FUNCTION__, __LINE__, "Error: Unexpect error in getsockopt");
            ret = SOCKET_FALSE;
        }
    }
    else
    {
        DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_DETAIL, __FUNCTION__, __LINE__, "Error: Connect failed");
        ret = SOCKET_FALSE;
    }
    return ret;
}
SOCKET_STATUS TestSockWriteable()
{
    SOCKET_BOOL ret;
    SOCKET_STATUS selecRet;
    fd_set writeset;
    TimeInfo timeout = g_stClient.timeout.Connect;
    
    FD_ZERO(&writeset);
    FD_SET(g_stClient.Sockfd, &writeset);
    selecRet = select(g_stClient.Sockfd+1, NULL, &writeset, NULL, &timeout);

    if(selecRet < 0)
    {
        DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "Error: Select failed");
        ret = SOCKET_FALSE;
    }
    else if(selecRet == 0)
    {
        DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_DETAIL, __FUNCTION__, __LINE__, "Error: Connect timeout");
        ret = SOCKET_FALSE;
    }
    else/* check if socket writeable*/
    {
        if(CanSockWrite(&writeset))
        {
            ret = SOCKET_TRUE;
        }
        else
        {
            ret = SOCKET_FALSE;
        }
    }
    return ret;
}
SOCKET_STATUS CheckConnStatus()
{
    SOCKET_STATUS ret = SOCKET_ERROR;
    
    if(errno != EINPROGRESS)/* 连接不在进行中,出现错误*/
    {
        DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_DETAIL, __FUNCTION__, __LINE__, "Error: Connect failed");

        if(errno == EISCONN)/*  关闭连着状态的服务 */
        {
            close(g_stClient.Sockfd);
            g_stClient.Sockfd = SOCKET_ERROR;
            g_stClient.ClientSts = CLIENT_INIT;
        }

        ret = SOCKET_ERROR;
    }
    else/* connection is under porgress */
    {
        if(TestSockWriteable())
        {
            ret = SOCKET_OK;
        }
        else
        {
            ret = SOCKET_ERROR;
        }
    }
    return ret;
}
/* 设置超时连接,连接超时返回错误 */
SOCKET_STATUS ClientConnectServer()
{
    SOCKET_STATUS ret = SOCKET_ERROR;
    
    NON_BLOCK();
    
    if(NonblockConnect() == SOCKET_ERROR)/* under process:非阻塞模式,返回值-1不表示错误 */
    {
        ret = CheckConnStatus();
    }
    else/* connect success */
    {
        DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "Success: Connect OK!");
        ret = SOCKET_OK;
    }
    
    BLOCK();

    return ret;
}
void ChangeSocketServerInfo(CHAR *pServer, UINT32 port)
{
    if (pServer != NULL && strcmp(pServer, g_stClient.ServerIp) != 0)
    {
        memcpy(g_stClient.ServerIp, pServer, strlen(pServer));
        g_stClient.ServerIp[strlen(pServer)] = '\0';
    }
    if (port != 0 && port != g_stClient.ServerPort)
    {
        g_stClient.ServerPort = port;
    }

    g_stClient.ClientSts = CLIENT_CHANGE_SERVER;
}

INT32 TcpClientSend(BYTE *buf, WORD32 len)
{
    INT32 sendNum = 0;
    
    if((g_stClient.Sockfd < 0) || (g_stClient.ClientSts != CLIENT_RUNNING))
    {
        return SOCKET_ERROR;
    }
    if(SOCKET_SND_DEBUG)
    {
        printf("socket send data len %d; data: \n", len);
        ShowHexData(buf, len);
        printf("\n");
    }
    sendNum = send(g_stClient.Sockfd, buf, len, 0);
    if(sendNum < 0)
    {
        /* TO-DO:send failed */
    }
    return sendNum;
}

SOCKET_STATUS ClientRecv()
{
    INT32 recvNum = 0;
    
    if(g_stClient.Sockfd < 0)
    {
        return SOCKET_ERROR;
    }
    memset(g_stClient.Buffer, 0, CLIENT_RECV_BUFF_SIZE);
    recvNum = recv(g_stClient.Sockfd, g_stClient.Buffer, CLIENT_RECV_BUFF_SIZE, 0);

    return recvNum;
}

SOCKET_STATUS SetClientTimeout()
{
    SOCKET_STATUS ret;
    
    if(g_stClient.Sockfd < 0)
    {
        return SOCKET_ERROR;
    }

    ret = setsockopt(g_stClient.Sockfd, SOL_SOCKET, SO_RCVTIMEO, &g_stClient.timeout.Recv,sizeof(TimeInfo));
    ret = setsockopt(g_stClient.Sockfd, SOL_SOCKET, SO_SNDTIMEO, &g_stClient.timeout.Send,sizeof(TimeInfo));

    return ret;
}
SOCKET_STATUS ModifyClientTimeout(TimeInfo send, TimeInfo recv)
{
    SOCKET_STATUS ret;
    
    if(g_stClient.Sockfd < 0)
    {
        return SOCKET_ERROR;
    }
    g_stClient.timeout.Recv = recv;
    g_stClient.timeout.Send = send;
    ret = SetClientTimeout();
    
    return ret;
}
SOCKET_STATUS ClientRecvHandler(BYTE *data, INT32 len)
{
    if(NULL == data || NULL == g_stClient.RecvHandler)
    {
        return SOCKET_ERROR;
    }
    if(IsModLogOn(LOG_MDL_TCP_CLIENT))
    {
        DmsaLog(LOG_MDL_TCP_CLIENT, LOG_LEVEL_BASIC, __FUNCTION__, __LINE__, "Client recv %d data", len);
        ShowHexData((WORD8 *)data, len);
    }

    return g_stClient.RecvHandler(data, len);
}
void StopClient()
{
    g_stClient.ClientSts = CLIENT_STOPPED;
}
void StartClient()
{
    g_stClient.ClientSts = CLIENT_RUNNING;
}
ClientStatus GetClientStatus()
{
    return g_stClient.ClientSts;
}
void RegisterRecvHandler(func handler)
{
    g_stClient.RecvHandler = handler;
}
SOCKET_STATUS ClientRecving()
{
    INT32 recvNum = 0;
    SOCKET_STATUS iRet = SOCKET_OK;
    
    recvNum = ClientRecv();

    if(recvNum < 0)
    {
        OdvsTaskDelay(100);
    }
    else if(recvNum == 0)/* connect is terminated */
    {
        iRet = SOCKET_ERROR;
        close(g_stClient.Sockfd);
        OdvsTaskDelay(100);
    }
    else if(recvNum > 0)
    {   
        ClientRecvHandler(g_stClient.Buffer, recvNum);
        OdvsTaskDelay(1);
    }
    
    return iRet;
}
SOCKET_STATUS CreateOkMoveNext(SOCKET_STATUS sts, INT32 delay)
{
    SOCKET_BOOL ret = SOCKET_TRUE;
    
    if(SOCKET_ERROR == sts)
    {
        OdvsTaskDelay(delay);
        ret = SOCKET_FALSE;
    }
    
    return ret;
}
SOCKET_STATUS ConnectOkMoveNext(SOCKET_STATUS sts, INT32 delay)
{
    SOCKET_BOOL ret = SOCKET_TRUE;
    
    if(SOCKET_ERROR == sts)
    {
        OdvsTaskDelay(delay);
        ret = SOCKET_FALSE;
    }
    else
    {   
        SetClientTimeout();
    }
    return ret;
}
SOCKET_STATUS RecvErrMoveNext(SOCKET_STATUS sts, INT32 delay)
{
    SOCKET_BOOL ret = SOCKET_TRUE;
    if(SOCKET_OK == sts)
    {
        OdvsTaskDelay(delay);
        ret = SOCKET_FALSE;
    }
    return ret;
}
SOCKET_STATUS ClientRun(INT32 arg1, INT32 arg2, INT32 arg3, INT32 arg4, INT32 arg5,
                       INT32 arg6, INT32 arg7, INT32 arg8, INT32 arg9, INT32 arg10)
{   
    INT32 iDefaultDelay = 100; /* 100 * 10ms */

    while(SOCKET_TRUE)
    {
        switch(g_stClient.ClientSts)
        {
            case CLIENT_INIT:
                if(CreateOkMoveNext(ClientCreateSocket(), iDefaultDelay))
                {
                    g_stClient.ClientSts = CLIENT_CONNECT;
                }
                break;
            case CLIENT_CONNECT:
                if(ConnectOkMoveNext(ClientConnectServer(), iDefaultDelay))
                {
                    g_stClient.ClientSts = CLIENT_RUNNING;
                    if (SOCKET_OK == GetRouteMacAddr(g_stClient.Sockfd, g_stClient.gatewayMac))
                    {
                        SetUdpServerCtrlIf(0, g_stClient.gatewayMac, ntohl(inet_addr(g_stClient.ServerIp)), g_stClient.ServerPort);
                        SetUdpServerCtrlIf(1, g_stClient.gatewayMac, ntohl(inet_addr(g_stClient.ServerIp)), g_stClient.ServerPort);
                    }
                }
                break;
            case CLIENT_RUNNING:
                if(RecvErrMoveNext(ClientRecving(), iDefaultDelay))
                {
                    g_stClient.ClientSts = CLIENT_INIT;
                }
                break;
            case CLIENT_CHANGE_SERVER:
                CloseSocket();
                g_stClient.ClientSts = CLIENT_INIT;
                break;
            case CLIENT_STOPPED:
                OdvsTaskDelay(200);
                break;
            default:
                OdvsTaskDelay(100);
                break;
        }
    }
}
SOCKET_STATUS StartupClientThread()
{
    return OdvsTaskSpawn("ClientTcp", 90, 0, 0x2000, (ODVS_FUNCPTR)ClientRun, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
SOCKET_STATUS StartTcpClientMdl()
{
    SOCKET_STATUS ret = SOCKET_ERROR;
    
    g_stClient.ClientSts = CLIENT_INIT;
    StartupClientThread();

    return ret;
}
/***********************HELP*******************/
void ShowClientInfoHelp()
{
    CHAR *sts[] = {"CLIENT_STOPPED", "CLIENT_INIT", "CLIENT_CONNECT","CLIENT_RUNNING", "CLIENT_CHANGE_SERVER"};

    printf("\n===============================================");
    printf("\n------------Client Information-----------------\n");
    printf("Client Status          : %s\n", sts[g_stClient.ClientSts]);
    printf("Client Socket FD       : %d\n", g_stClient.Sockfd);
    printf("Client Server ip       : %s\n", g_stClient.ServerIp);
    printf("Client Server port     : %d\n", g_stClient.ServerPort);
    printf("Client timeout connect : %ld\n", g_stClient.timeout.Connect.tv_sec);
    printf("Client timeout Send    : %ld\n", g_stClient.timeout.Send.tv_sec);
    printf("Client timeout Recv    : %ld\n", g_stClient.timeout.Recv.tv_sec);
    printf("Client recv buffer addr: %p\n", g_stClient.Buffer);
    printf("Client gateway mac addr: %s\n", g_stClient.gatewayMac);
    printf("handler                : %p\n", g_stClient.RecvHandler);
    printf("===============================================\n");
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值