现在的位置: 首页 > 综合 > 正文

网络的connect如何超时设置?MFC socket异步 timeout select

2018年05月28日 ⁄ 综合 ⁄ 共 1886字 ⁄ 字号 评论关闭

这个帖子很精彩:

http://bbs.csdn.net/topics/390416681?page=1

附关键代码:

	m_strServerIP = strServerIP;
	m_nPort = nPort;

	while( true )
	{
		// 创建套接字
		m_socket = socket(AF_INET,SOCK_STREAM,0);
		if( m_socket == INVALID_SOCKET )
			break;
		// 设置为非阻塞模式
		DWORD ul = 1;
		if( 0 != ioctlsocket( m_socket, FIONBIO, &ul) ) 
			break;
		// 将UNICODE的IP地址转换为多字节字符的IP地址
		char szServerIP[16] = { 0 };
		if( WideCharToMultiByte( CP_ACP,0,m_strServerIP,m_strServerIP.GetLength(),szServerIP,sizeof(szServerIP),NULL,NULL ) == 0 )
			break;
		// 连接指定的IP地址和端口
		SOCKADDR_IN sin;
		sin.sin_family = AF_INET;
		sin.sin_port = htons(m_nPort);
		sin.sin_addr.s_addr = inet_addr( szServerIP );
		if( ! ( SOCKET_ERROR == connect( m_socket, (SOCKADDR *)&sin, sizeof(sin)) && WSAGetLastError() == WSAEWOULDBLOCK ) )
			break;
		// 异步connect不会等待就直接返回了,用select的方式来判断connect是否成功,select会阻塞,只到connect连接成功或失败后select才返回
		fd_set fs_read;
		FD_ZERO( &fs_read );
		FD_SET( m_socket,&fs_read );
		fd_set fs_write;
		fs_write.fd_count = 1;
		fs_write.fd_array[0] = m_socket;
		fd_set fs_error;
		fs_error.fd_count = 1;
		fs_error.fd_array[0] = m_socket;
		int ret = select( 0,&fs_read,&fs_write,&fs_error,NULL );
		if( ret == SOCKET_ERROR )
			break;
		// 判断socket句柄是否可写
		if( !FD_ISSET( m_socket,&fs_write ) )
			break;
		int optval = -1;
		int optlen = sizeof(optval);
		ret = getsockopt( m_socket,SOL_SOCKET,SO_ERROR,(char*)(&optval),&optlen );
		if( ret != 0 || optval != 0)
			break;
		// 直到这里connect才是真正成功
		// 创建监听线程收到消息的事件句柄
		m_wsaEvent = WSACreateEvent();
		if( m_wsaEvent == WSA_INVALID_EVENT )
			break;
		// 给监听线程的消息到达事件句柄配置要通知的事件类型
		if( WSAEventSelect( m_socket,m_wsaEvent,FD_READ|FD_WRITE|FD_CONNECT|FD_CLOSE ) != 0 )
			break;
		// 创建通知监听线程退出的事件句柄
		m_wsaClose = WSACreateEvent();
		if( m_wsaClose == WSA_INVALID_EVENT )
			break;
		// 创建消息事件监听线程
		DWORD dwThreadId;
		m_hThreadEvent = CreateThread( NULL, 0, ThreadProc_SocketEvent, this, 0, &dwThreadId );
		if( m_hThreadEvent == NULL )
			break;
		// 创建定时发送心跳包的事件句柄
		m_hEventHeartbeat= CreateEvent( NULL,TRUE,FALSE,NULL );
		if( m_hEventHeartbeat == NULL )
			break;
		// 创建定时发送心跳包的线程
		m_hThreadHeartbeat = CreateThread( NULL,0,ThreadProc_Heartbeat,this,0, &dwThreadId );
		if( m_hThreadHeartbeat == NULL )
			break;
		// 全部创建成功,返回TRUE
		return TRUE;
	}

抱歉!评论已关闭.