Re: Non blocking connect()
I think I managed to get it working in Linux, not to figure how to get it working in windows. Wish they'd just standardize all these functions so it works cross platform accross the board.
Code:
bool SocketClient::Connect()
{
#ifdef WIN32
WSADATA wsaData;
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
{
status=2;
return false;
}
#endif
sockfd = socket(PF_INET, SOCK_STREAM, 0);
if ((he=gethostbyname(ip.c_str())) == NULL) { // get the host info
status=2;
return false;
}
#ifndef WIN32
//declare some temp vars:
fd_set myset;
struct timeval tv;
socklen_t lon;
// Set non-blocking:
int valopt;
long arg = fcntl(sockfd, F_GETFL, NULL);
arg |= O_NONBLOCK;
fcntl(sockfd, F_SETFL, arg);
#endif
// Try to connect:
dest_addr.sin_family = AF_INET; // host byte order
dest_addr.sin_port = htons(port); // short, network byte order
dest_addr.sin_addr = *((struct in_addr *)he->h_addr);
memset(dest_addr.sin_zero, '\0', sizeof dest_addr.sin_zero);
int res = connect(sockfd, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
#ifndef WIN32
if (res < 0) {
if (errno == EINPROGRESS) {
tv.tv_sec = m_contimeoutsec;
tv.tv_usec = m_contimeoutusec;
FD_ZERO(&myset);
FD_SET(sockfd, &myset);
if (select(sockfd+1, NULL, &myset, NULL, &tv) > 0) {
lon = sizeof(int);
getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon);
if (valopt)
{
status=2;
return false;
}
}
else {
status=2;
return false;
}
}
else {
status=2;
return false;
}
}
// Set to blocking mode again:
arg = fcntl(sockfd, F_GETFL, NULL);
arg &= (~O_NONBLOCK);
fcntl(sockfd, F_SETFL, arg);
#else
if(res==-1) //TODO: Find a way to setup non blocking sockets in win32 so it does not try to connect forever
{
status=2;
return false;
}
#endif
status=1;
return true;
}
Re: Non blocking connect()
I think Windows return WSAEWOULDBLOCK on a non-blocking socket.
And you might want to use setsockopt to set the socket to nonblocking, that looks more intuitive to me.
BTW, connect does not try forever. The 'normal' timeout would be about 20 seconds, but I have seen longer times, but definitely not forever.
HTH,
Richard
Re: Non blocking connect()
dont know if this helps - i have been using CAsyncSocket as both a client and a server to get into sockets. i stubbed my toe trying to connect and WSAEWOULDBLOCK was returned indicating an attempt to a non-blocking socket failed because there was no immediate connection.
i use the following code to continue to attempt to connect and it works now. strangely (in my mind) the second attempt would also fail because now the
socket complains that the sonnection already exists.
i use the following code to set up a series of attempts to connect and have not had a failure yet the basic idea is to keep tyring to connect and get the last error if the return form the connect attempt is 0 BUT determine the connection has been made if the GetLasError() fn sas the conneciton exists:
Code:
ErrorCode = SocketToSend.Create(); // no parms because it is a client
if (ErrorCode == 0){
MessageBox(
_T("Faliure on SocketToSend.Create()"),
Mode,
MB_OK
);
}
else{
// use it to listen
bool FinallyGotAConnection = FALSE;
bool StopThis = FALSE;
int i = 0;
while (StopThis == FALSE){
ErrorCode = SocketToSend.Connect(LPCTSTR(Server),Port);
if (ErrorCode != 0){
FinallyGotAConnection = TRUE;
StopThis = TRUE;
}
else{
LastError = GetLastError();
if (LastError == WSAEISCONN){
FinallyGotAConnection = TRUE;
StopThis = TRUE;
}
}
i++;
if (i > 100){
StopThis = TRUE;
}
}
if (FinallyGotAConnection == FALSE){
s = GetErrorText(_T("connect"));
MessageBox(
_T("SocketToSend.Connect(LPCTSTR(Server),Port) fail - error ") + s,
Mode,
MB_OK
);
}
else{
MessageBox(
_T("SocketToSend.Connect(LPCTSTR(Server),Port) completed"),
Mode,
MB_OK
);
}
}
Re: Non blocking connect()
jim, you did not understand what I tried to explain. As Red Squirrel and you expirienced, calling connect on a non-blocking socket will lead to an error. This is per definition, as a real connection might take some seconds. The error code connect() returns simply indicates this. Under the hood the TCP stack still performs its task to try and establish the desired connection.
Now, to get an indication when the connection really is available, you could use select() on the low level API or wait for the OnConnect() event on the CAsyncSocket API. Both ways are equivalent because the CAsyncSocket makes use of the lower level Windows/BSD socket API.
The approach Red Squirrel took is correct, except that he/she uses the wrong error code on Windows.
HTH,
Richard
Re: Non blocking connect()
how does one wait for the onconnect event?
Re: Non blocking connect()
Assuming you are using CAsyncSocket as you stated in that other thread of yours, derive your class from CAsyncSocket and overwrite the virtual OnConnect() method. You might want to read the docs on MSDN on this topic (http://msdn.microsoft.com/en-us/libr...5f(VS.80).aspx)