socket_client_tcp 今天药忘吃喽~ 2022-03-15 07:46 205阅读 0赞 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"); }
还没有评论,来说两句吧...