select()检测非阻塞connect状态

2013年7月2日 由 Creater 留言 »

1.将打开的socket设为非阻塞的,可以用fcntl(socket, F_SETFL, O_NDELAY).

2.发connect调用,这时返回-1,但是errno被设为EINPROGRESS,意即connect仍旧在进行还没有完成.

3.将打开的socket设进被监视的可写,文件集合用select进行监视, 如果可写,用
getsockopt(socket, SOL_SOCKET, SO_ERROR, &error, sizeof(int));
来得到error的值,如果为零,则connect成功.
比如如下的应用:

void TcpSocket::OnWrite()
{
	//Connecting表示该连接还在尝试连接但是并未建立。
	//此时出现可读事件OnWrite表明
	if (Connecting())
	{
		int err = SoError();

		// don't reset connecting flag on error here, we want the OnConnectFailed timeout later on
		if (!err) // ok
		{
		//如果error为0,则表示connect连接成功
			Handler().ISocketHandler_Mod(this, !IsDisableRead(), false);
			SetConnecting(false);
			SetCallOnConnect();
			return;
		}
		Handler().LogError(this, "tcp: connect failed", err, StrError(err), LOG_LEVEL_FATAL);
		Handler().ISocketHandler_Mod(this, false, false); // no more monitoring because connection failed

		// failed
		if (GetConnectionRetry() == -1 ||
			(GetConnectionRetry() && GetConnectionRetries() < GetConnectionRetry()) )
		{
			// even though the connection failed at once, only retry after
			// the connection timeout.
			// should we even try to connect again, when CheckConnect returns
			// false it's because of a connection error - not a timeout...
			return;
		}
		SetConnecting(false);
		SetCloseAndDelete( true );
		/// \todo state reason why connect failed
		OnConnectFailed();
		return;
	}
	SendFromOutputBuffer();
}

Connecting()获取connect的用户状态,这个状态是由用户手动改变,当connect发起至未连接完成时,Connecting()都返回true。连接成功后,由用户调用 SetConnecting(false)进行状态改变。

当出现可写事件(OnWrite)时,如果当前正在connect,则通过SoError()检查状态,如果为0则表示连接成功。

广告位

发表评论

你必须 登陆 方可发表评论.