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");
}