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

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

#include 
#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_DATA	WM_USER+201		// 网络接受数据
#define WM_TCP_CONNECT		WM_USER+202		// 网络连接
#define WM_TCP_DISCONNECT	WM_USER+203		// 网络断开

#define RECV_BUFFER_SIZE	1024


// 设置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 message
				char 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;
}

你可能感兴趣的:(VC应用)