socket_ex用到的相关API是Linux下通用的接口,可在Linux环境下通过man命令查询到。
本章节主要介绍如何在 SDK 中使用 example_socketex.c。
#include
#include
#include
#include
#include
#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");
}