问题
Our application uses a non-blocking socket usage with connect and select operations (c code). The pusedo code is as below
unsigned int ConnectToServer(struct sockaddr_in *pSelfAddr,struct sockaddr_in *pDestAddr)
{
int sktConnect = -1;
sktConnect = socket(AF_INET,SOCK_STREAM,0);
if(sktConnect == INVALID_SOCKET)
return -1;
fcntl(sktConnect,F_SETFL,fcntl(sktConnect,F_GETFL) | O_NONBLOCK);
if(pSelfAddr != 0)
{
if(bind(sktConnect,(const struct sockaddr*)(void *)pSelfAddr,sizeof(*pSelfAddr)) != 0)
{
closesocket(sktConnect);
return -1;
}
}
errno = 0;
int nRc = connect(sktConnect,(const struct sockaddr*)(void *)pDestAddr, sizeof(*pDestAddr));
if(nrC != -1)
{
return sktConnect;
}
if(errno != EINPROGRESS)
{
int savedError = errno;
closesocket(sktConnect);
return -1;
}
fd_set scanSet;
FD_ZERO(&scanSet);
FD_SET(sktConnect,&scanSet);
struct timeval waitTime;
waitTime.tv_sec = 2;
waitTime.tv_usec = 0;
int tmp;
tmp = select(sktConnect +1, (fd_set*)0, &scanSet, (fd_set*)0,&waitTime);
if(tmp == -1 || !FD_ISSET(sktConnect,&scanSet))
{
int savedErrorNo = errno;
writeLog("Connect %s failed after select, cause %d, error %s",inet_ntoa(pDestAddr->sin_addr),savedErrorNo,strerror(savedErrorNo));
closesocket(sktConnect);
return -1;
}
.
.
.
.
.}
Problem statement
In the above code, the select
fails with error code 115
which is "Operation in progress". I do not see any documentation on select
failing with errno 115
.
a. When does the select
fails with error code 115
in non-blocking socket? Under what scenario?
b. Do we see any system logs which hints at this problem. Only concern for us me - I could not find any documented feature which describes such problem.
PS : We are using SUSE Linux 11 Enterprise Edition.
回答1:
Some thoughts on your code:
I think your condition below the select can be modified to check only to see, if select has returned a value greater than 0 and if that is the case, you can check output of getsockopt for the socket (for SOL_SOCKET and SO_ERROR) options (getsockopt(...,SOL_SOCKET, SO_ERROR,...,...)
) to see if connect has not failed.
I am not very sure if the select will always return the socket as writable in case of a connection success. So, in your case, it may (only may) be the case that, the tmp variable is not -1 and the errno it is showing is the errno of the previous connect call.
Additional Reasons:
Another good reason is that, the destination address to which you are connecting is either not reachable, or doesn't have a server waiting at the specified address + port combination. In which case, you can try once with a blocking socket to see if that connects.
回答2:
The errno EINPROGRESS isn't from select(), it is left over from the prior connect() operation. You enter the block that reports it if either select() returned -1 or the FD isn't set. All this means is that the connection is still in progress. errno is never cleared, only set.
回答3:
As far as I understand, you are trying to make a connection with timeout.
If so, there is a error in your code. After connect()
call but before select()
you should remove O_NONBLOCK
option using fcntl()
. Otherwise the select()
will always return at once because the operations with your socket (which has O_NONBLOCK
) would not block.
The EINPROGRESS which you read is probably generated not by select()
but by previous connect()
call.
You also should not use bind()
call here because connect()
implicitly binds your address to socket.
来源:https://stackoverflow.com/questions/11151140/socket-select-fails-with-operation-in-progress-non-blocking-mode