12. M601 socket_ex的使用

1 socket_ex 相关API

socket_ex用到的相关API是Linux下通用的接口,可在Linux环境下通过man命令查询到。

2 socket_ex 例程介绍

本章节主要介绍如何在 SDK 中使用 example_socketex.c。


#include <stdint.h>

#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/errno.h>

#include "zyf_app.h"

#include "zyf_trace.h"
#include "zyf_timer.h"
#include "zyf_thread.h"
#include "zyf_socket_ex.h"

/* tcp client */
static ZYF_SockParam_t s_tTCPParam;
static ZYF_SockClient_t s_tTCPClient;

static Uart_Param_t g_uart1param;


void UartWriteCallBack(void* Param) // general com
{
    Uart_Param_t *uartparam = (Uart_Param_t *)Param; 
    if(Param == NULL)
    {
        return;
    }    

    ZYF_UartWrite(uartparam->port,(uint8_t *)"UartWrite succeed\r\n",strlen("UartWrite succeed\r\n"));
    ZYF_UartWriteCallbackSwitch(uartparam->port,false);

}

void UartReadCallBack(void* Param) // 
{
    uint32_t recvlen = 0;
    Uart_Param_t *uartparam = (Uart_Param_t *)Param; 

    /*
    UART_PORT1 = 0,
    UART_PORT2 = 1,
    UART_PORT3 = 2,
    */
    ZYF_LOG("Uart%d recv",uartparam->port);

    while(ZYF_UartRead(uartparam->port, &(uartparam->uartbuf[recvlen]), 1))
    {
        ZYF_LOG("recv :%02x",uartparam->uartbuf[recvlen]);
        recvlen++;
    }
    ZYF_UartWrite(uartparam->port,uartparam->uartbuf,recvlen);
    ZYF_UartWriteCallbackSwitch(uartparam->port,true);
}


static void AppUartInit(void)
{
    int32_t ret;
    g_uart1param.port = DEBUG_PORT;
    ZYF_UartRegister(g_uart1param.port, UartReadCallBack,&g_uart1param);
    ZYF_UartWriteCbRegister(g_uart1param.port,UartWriteCallBack,&g_uart1param);
    ZYF_UartOpen(g_uart1param.port, 115200, ZYF_FC_NONE);

    ZYF_LOG("AppUartInit");
    return;
}


void ZYF_TcpPdpActCallback(uint8_t status)
{
    ZYF_SockClient_t *ptClient = &s_tTCPClient;
    ZYF_AppMsg_t tMsg;

    if (ptClient->ptParam != NULL) {
        tMsg.wMsgId = status;
        ZYF_MsgQPut(ptClient->ptParam->ptMsg, (void *)&tMsg);
    }
}


void ZYF_PdpActiveCnf(uint8_t contextId, int32_t errCode)
{
    ZYF_LOG("PDP: Active");

    ZYF_TcpPdpActCallback(APP_MSG_PDP_ACTIVE);
}

void ZYF_PdpDeactiveCnf(uint8_t contextId, int32_t errCode)
{
    ZYF_LOG("PDP: Deactive");
}



static void ZYF_TCPReconnReqEx(void)
{
    ZYF_SockClient_t *ptClient = &s_tTCPClient;
    ZYF_AppMsg_t tMsg;
    
    if (!ptClient->ptParam->bConnected) {
        tMsg.wMsgId = APP_MSG_TCP_RECONN;
        ZYF_MsgQPut(ptClient->ptParam->ptMsg, (void *)&tMsg);
    }
}

static void ZYF_TCPReconnCallbackEx(void *pvArg)
{
    ZYF_SockClient_t *ptClient = (ZYF_SockClient_t *)pvArg;
    
    ZYF_TCPReconnReqEx();
    ZYF_StopTimer(ptClient->ptParam->ptConnTimer);
}

static void ZYF_TCPSendDataReqEx(uint8_t *pchBuffer, uint16_t hwLen)
{
    ZYF_SockClient_t *ptClient = &s_tTCPClient;
    ZYF_AppMsg_t tMsg;
    
    if (ptClient->ptParam->bConnected) {
        tMsg.wMsgId = APP_MSG_TCP_SEND;  
        ptClient->ptParam->hwTxSize = hwLen;
        memcpy((void *)ptClient->ptParam->chTxBuffer, pchBuffer, hwLen);
        
        ZYF_MsgQPut(ptClient->ptParam->ptMsg, (void *)&tMsg);
    }
}

static void ZYF_TCPTimerCallbackEx(void *pvParam)
{
    ZYF_SockClient_t *ptClient = (ZYF_SockClient_t *)pvParam;
    const char *pcStr = "Hello, world! ^_^\r\n";

    ZYF_TCPSendDataReqEx((uint8_t *)pcStr, strlen(pcStr));
    ZYF_StartTimer(ptClient->ptParam->ptSendTimer, 5000);
}

static void ZYF_TCPRecvThreadEx(void *pvParam)
{
    ZYF_SockClient_t *ptClient = (ZYF_SockClient_t *)pvParam;
    struct sock_fd_set readfds;
    int iRet = -1;
    struct timeval tv;
    

    ZYF_LOG("thread enter!");
    
    while (1) {
        if (!ptClient->ptParam->bConnected) {
            ZYF_TCPReconnReqEx();
            ZYF_ThreadDelete();
            ZYF_LOG("thread exit!");
            return;
        }

        SOCK_FD_ZERO(&readfds);
        SOCK_FD_SET(ptClient->nSockFd, &readfds);
        tv.tv_sec = 10;
        tv.tv_usec = 0;

        iRet = socket_select(ptClient->nSockFd + 1, &readfds, NULL, NULL, &tv);
        switch (iRet) {
            case -1:
                ZYF_LOG("recv error!");
                break;
            case 0:
                ZYF_LOG("recv timeout!");
                break;
            default:
                if (SOCK_FD_ISSET(ptClient->nSockFd, &readfds)) {
                    iRet = socket_recv(ptClient->nSockFd, ptClient->ptParam->chRxBuffer, SOCKET_RECV_MAX_SIZE, 0);
                    if (iRet <= 0 && (socket_geterrno() == ENOTCONN || socket_geterrno() == ECONNRESET)) {
                        socket_close(ptClient->nSockFd);
                        ptClient->nSockFd = -1;
                        ptClient->ptParam->bConnected = 0;
                        ZYF_LOG("recv error! => %d", socket_geterrno());
                    } else {
                        ptClient->ptParam->hwRxSize = iRet;
                        ZYF_LOG("recv tcp ok => len: %d, %s", ptClient->ptParam->hwRxSize, ptClient->ptParam->chRxBuffer);
                        memset((void *)ptClient->ptParam->chRxBuffer, 0, SOCKET_RECV_MAX_SIZE);
                    }
                }
                break;
        }
    }
}

static int __ZYF_TCPClientConnEx(const char *host, uint16_t port)
{
    struct sockaddr_in sAddr;
    struct hostent *host_entry = NULL;
    int fd = -1;
	int retVal = -1;
	
    if ((host_entry = socket_gethostbyname(host)) == NULL) {
        ZYF_LOG("dns parse error!");
		goto exit;
	}

    sAddr.sin_family = AF_INET;
	sAddr.sin_port   = htons(port);
	sAddr.sin_addr   = *(struct in_addr *)host_entry->h_addr_list[0];

	if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
		goto exit;
	}

    struct timeval tv;
	tv.tv_sec = 8;
	tv.tv_usec = 0;

	sock_fd_set readfds, writefds;
    int error;
    socklen_t optlen = sizeof(error);
	
	SOCK_FD_ZERO(&readfds);
	SOCK_FD_ZERO(&writefds);
	SOCK_FD_SET(fd, &readfds);
	SOCK_FD_SET(fd, &writefds);

    socket_fcntl( fd, F_SETFL, O_NONBLOCK );
	
    retVal = socket_connect(fd, (struct sockaddr*)&sAddr, sizeof(sAddr));
    if (retVal == 0) {
        ZYF_LOG("connect success....\n");
    } else {
        retVal = socket_select(fd+1, &readfds, &writefds, NULL, &tv);
        switch(retVal) {
            case -1:
                ZYF_LOG("connect failed!");
	            goto exit;
                break;
            case 0:
                ZYF_LOG("connect timeout!");
	            goto exit;
                break;
            default:
                if(!SOCK_FD_ISSET(fd, &readfds) && !SOCK_FD_ISSET(fd, &writefds)) {
                    ZYF_LOG("connect no response\n");
                    goto exit;
                } else if(SOCK_FD_ISSET(fd, &readfds) && SOCK_FD_ISSET(fd, &writefds)) {
                    retVal = socket_getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &optlen);
                    if(retVal == 0 && error == 0) {
                        ZYF_LOG("connect success....\n");
                    } else {
                        ZYF_LOG("connect error....\n");
                        goto exit;
                    }
                } else if(!SOCK_FD_ISSET(fd, &readfds) && SOCK_FD_ISSET(fd, &writefds)) {
                    ZYF_LOG("connect success....\n");
                } else {
                    ZYF_LOG("connect error....\n");
                    goto exit;
                }
                break;
        }
	}
	
	int old_option = socket_fcntl( fd, F_GETFL, 0);
    int new_option = old_option & (~O_NONBLOCK);
    socket_fcntl( fd, F_SETFL, new_option );
    
	return (int)fd;

exit:
    if (fd > 0) {
        socket_close(fd);
    }
    retVal = -1;
    return retVal;
}

static void ZYF_TCPClientConnEx(ZYF_SockClient_t *ptClient)
{
    int fd;
    char ipddr[16] = {0};
    
    sprintf(ipddr, "%d.%d.%d.%d", ptClient->chIpAddr[0], ptClient->chIpAddr[1],ptClient->chIpAddr[2],ptClient->chIpAddr[3]);
    fd = __ZYF_TCPClientConnEx(ipddr, ptClient->hwPort);
    if (fd > 0) {
        ptClient->nSockFd = fd;
        ZYF_LOG("tcp client connect OK! => %d", fd);
        ptClient->ptParam->bConnected = true;
        ZYF_StartTimer(ptClient->ptParam->ptSendTimer, 5000);
        ZYF_ThreadCreate("ZYF_TCPRecvThread", ZYF_TCPRecvThreadEx, (void *)&s_tTCPClient, ZYF_PRIORITY_NORMAL, 1024 * 2);
    } else {
        if (fd > 0) {
            socket_close(fd);
        }
        ZYF_StartTimer(ptClient->ptParam->ptConnTimer, 10000);
    }
}

static void ZYF_TCPClientThreadEx(void *pvParam)
{
    ZYF_SockClient_t *ptClient = (ZYF_SockClient_t *)pvParam;
    ZYF_AppMsg_t tMsg;
    int iRet = -1;

    ZYF_LOG("thread enter!");

    while (1) {
        iRet = ZYF_MsgQGet(ptClient->ptParam->ptMsg, (void *)&tMsg);
        if (iRet < 0) {
            ZYF_LOG("Failed to get msg");
            ZYF_ThreadSleep(10);
        }

        switch (tMsg.wMsgId) {
            case APP_MSG_PDP_ACTIVE:
                ZYF_LOG("PDP active!");

                ZYF_TCPClientConnEx(ptClient);
                break;
                
            case APP_MSG_PDP_DEACTIVE:
                ZYF_LOG("PDP Deactive!");
                ZYF_StopTimer(ptClient->ptParam->ptSendTimer);
                if (!socket_close(ptClient->nSockFd)) {
                    ZYF_LOG("tcp socket close ok");
                    ptClient->ptParam->bConnected = false;
                }
                break;

            case APP_MSG_TCP_RECONN:
                ZYF_TCPClientConnEx(ptClient);
                break;

            case APP_MSG_TCP_SEND:
                if (ptClient->ptParam->hwTxSize > 0) {
                    uint16_t hwSentLen = 0;
                    int rc = 0;
                    
                    struct timeval timeout;
                    timeout.tv_sec = 5;
                    timeout.tv_usec = 0;
                    
                    do {
                        socket_setsockopt(ptClient->nSockFd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval));
                        rc = socket_send(ptClient->nSockFd, &ptClient->ptParam->chTxBuffer[hwSentLen], ptClient->ptParam->hwTxSize - hwSentLen, 0);
                        if (rc > 0) {
                            hwSentLen += rc;
                        } else if (iRet < 0) { 
                            ZYF_LOG("send failed! => %d", socket_geterrno());
                        } else if (iRet == 0 && (socket_geterrno() == ENOTCONN || socket_geterrno() == ECONNRESET)) {
                            socket_close(ptClient->nSockFd);
                            ptClient->nSockFd = -1;
                            ptClient->ptParam->bConnected = 0;
                            ZYF_LOG("send error! => %d", socket_geterrno());
                        }
                    } while (hwSentLen < ptClient->ptParam->hwTxSize);   //fixme: check if timeout here and then re-send

                    if (rc > 0) {
                        ZYF_LOG("sent tcp ok");
                    }
                }
                break;
                
            default:
                break;
        }
    }
}

void ZYF_TCPClientExTest(void)
{
    uint8_t chIpAddr[4] = {120,77,177,56};

    s_tTCPClient.nSockFd = -1;
    s_tTCPClient.hwPort = 4489;
    memcpy((void *)s_tTCPClient.chIpAddr, chIpAddr, 4);
    
    s_tTCPParam.bConnected = false;
    s_tTCPParam.bSent = false;
    s_tTCPParam.hwTxSize = 0;
    memset((void *)s_tTCPParam.chTxBuffer, 0, 1024);
    s_tTCPParam.hwRxSize = 0;
    memset((void *)s_tTCPParam.chRxBuffer, 0, 1024);

    s_tTCPClient.ptParam = &s_tTCPParam;
    s_tTCPClient.ptParam->ptMsg = ZYF_MsgQCreate(10, sizeof(ZYF_AppMsg_t));
    if (s_tTCPClient.ptParam->ptMsg != NULL) {
        ZYF_LOG("Succeeded to create network msg");
    }
    s_tTCPClient.ptParam->ptSendTimer = ZYF_CreateTimer(ZYF_TCPTimerCallbackEx, (void *)&s_tTCPClient);
    s_tTCPClient.ptParam->ptConnTimer = ZYF_CreateTimer(ZYF_TCPReconnCallbackEx, (void *)&s_tTCPClient);

    ZYF_ThreadCreate("ZYF_TCPClientThreadEx", ZYF_TCPClientThreadEx, (void *)&s_tTCPClient, ZYF_PRIORITY_NORMAL, 1024 * 2);
}


void TcpClientEx_Example(void * Param)
{
    ZYF_MsgQ_t *ptMsg;
    ZYF_AppMsg_t tMsg;
    int iRet = -1;
    ptMsg = ZYF_MsgQCreate(10, sizeof(ZYF_AppMsg_t));
    ZYF_LOG("thread enter!");

    ZYF_NetworkInit();
    ZYF_TCPClientExTest();
    while (1) {
        ZYF_LOG("in while.");
        iRet = ZYF_MsgQGet(ptMsg, (void *)&tMsg);
        if (iRet < 0) {
            ZYF_LOG("Failed to get msg");
            ZYF_ThreadSleep(1000);
        }
    }

}

static void prvInvokeGlobalCtors(void)
{
    extern void (*__init_array_start[])();
    extern void (*__init_array_end[])();

    size_t count = __init_array_end - __init_array_start;
    for (size_t i = 0; i < count; ++i)
        __init_array_start[i]();
}


int appimg_enter(void *param)
{
    AppUartInit();
    ZYF_LOG("application image enter, param 0x%x", param);

    prvInvokeGlobalCtors();

    ZYF_ThreadCreate("TcpClientEx_Example", TcpClientEx_Example, NULL, ZYF_PRIORITY_HIGH, 10*1024);
    return 0;
}

void appimg_exit(void)
{
    OSI_LOGI(0, "application image exit");
}

猜你喜欢

转载自blog.csdn.net/w_hizyf_m/article/details/107226912