VC下SOCKET通信,设置非阻塞模式,添加心跳检查

来源:互联网 发布:淘宝车秒贷怎么开通 编辑:程序博客网 时间:2024/06/06 05:21
/* VC下SOCKET通信,设置非阻塞模式,添加心跳检查 */#include <WINSOCK2.H>#pragma comment(lib, "ws2_32.lib")/* mstcpip.h */struct tcp_keepalive {    u_long onoff;    u_long keepalivetime;    u_long keepaliveinterval;};typedef struct tcp_keepalive TCP_KEEPALIVE;// New WSAIoctl Options#define SIO_RCVALL_WSAIOW(IOC_VENDOR,1)#define SIO_RCVALL_MCAST_WSAIOW(IOC_VENDOR,2)#define SIO_RCVALL_IGMPMCAST_WSAIOW(IOC_VENDOR,3)#define SIO_KEEPALIVE_VALS_WSAIOW(IOC_VENDOR,4)#define SIO_ABSORB_RTRALERT_WSAIOW(IOC_VENDOR,5)#define SIO_UCAST_IF_WSAIOW(IOC_VENDOR,6)#define SIO_LIMIT_BROADCASTS_WSAIOW(IOC_VENDOR,7)#define SIO_INDEX_BIND_WSAIOW(IOC_VENDOR,8)#define SIO_INDEX_MCASTIF_WSAIOW(IOC_VENDOR,9)#define SIO_INDEX_ADD_MCAST_WSAIOW(IOC_VENDOR,10)#define SIO_INDEX_DEL_MCAST_WSAIOW(IOC_VENDOR,11)/* mstcpip.h end */#define WM_TCP_RECV_DATAWM_USER+201// 网络接受数据#define WM_TCP_CONNECTWM_USER+202// 网络连接#define WM_TCP_DISCONNECTWM_USER+203// 网络断开#define RECV_BUFFER_SIZE1024// 设置socket心跳检测有效void SetKeepAlive(SOCKET sockfd){/* set socket keepalive mode */int alive = 1;setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (char *)&alive, sizeof(alive));/* set keepalive param */TCP_KEEPALIVE inKeepAlive = {0};unsigned long ulInLen = sizeof(TCP_KEEPALIVE);TCP_KEEPALIVE outKeepAlive = {0};unsigned long ulOutLen = sizeof(TCP_KEEPALIVE);unsigned long ulBytesReturn = 0;inKeepAlive.onoff = 1;inKeepAlive.keepaliveinterval = 500;//单位为毫秒inKeepAlive.keepalivetime = 100;//单位为毫秒WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, (LPVOID)&inKeepAlive, ulInLen, (LPVOID)&outKeepAlive, ulOutLen, &ulBytesReturn, NULL, NULL);// 设置socket为非阻塞u_long imode = 1; // 0为阻塞,非0为非阻塞ioctlsocket(sockfd, FIONBIO, &imode);}// 心跳检查函数UINT TcpKeepAliveThreadFunc(LPVOID pParam){SOCKET sockfd;sockfd = (SOCKET)pParam;BOOL bKeepAlive = TRUE;while (bKeepAlive){fd_set rfds;fd_set wfds;fd_set efds;/* 把集合清空 */        FD_ZERO(&rfds);FD_ZERO(&wfds);FD_ZERO(&efds);/* 把当前连接句柄sockfd加入到集合中 */        FD_SET(sockfd, &rfds);FD_SET(sockfd, &wfds);FD_SET(sockfd, &efds);/* 设置最大等待时间 */timeval tv;        tv.tv_sec = 1;        tv.tv_usec = 0;/* 开始等待 */int ret = select(sockfd+1, &rfds, &wfds, &efds, &tv);if (ret < 0){TRACE("<%s> select error!\n", __FILE__);// Sleep(100);}else if (ret == 0){TRACE("<%s> timeout!\n", __FILE__);PostMessage(AfxGetMainWnd()->m_hWnd, WM_TCP_DISCONNECT, NULL, NULL);bKeepAlive = FALSE;}else{if (FD_ISSET(sockfd, &rfds)){// read messagechar buffer[RECV_BUFFER_SIZE];memset(buffer, 0, sizeof(buffer));int ret = recv(sockfd, buffer, sizeof(buffer), 0);TRACE("<%s> DATA[%s]\n", __FILE__, buffer);if (ret > 0){PostMessage(AfxGetMainWnd()->m_hWnd, WM_TCP_RECV_DATA, (WPARAM)buffer, NULL);}else if (ret == 0){// 主动断开PostMessage(AfxGetMainWnd()->m_hWnd, WM_TCP_DISCONNECT, NULL, NULL);bKeepAlive = FALSE;}else if (ret < 0){// 拔掉网线PostMessage(AfxGetMainWnd()->m_hWnd, WM_TCP_DISCONNECT, NULL, NULL);bKeepAlive = FALSE;}}}}return 0;}