Solved

Timeout For a Connection

Posted on 2003-11-18
12
1,619 Views
Last Modified: 2007-12-19
Experts,

I am using winsock 2.  Is there a way during a connect() to set it's timeout value or is the timeout based on the network or lan.
0
Comment
Question by:acbirdie
  • 7
  • 4
12 Comments
 
LVL 86

Expert Comment

by:jkr
Comment Utility
See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/socket_options_for_windows_nt_and_windows_95_98_me_2.asp ("Socket Options for Windows NT and Windows Me/98/95") on how to do that with WS2:


To set a send time-out, use:

int timeout = TIMEOUT_VALUE;
int err;
SOCKET s;

s = socket( ... );
err = setsockopt(
        s,
        SOL_SOCKET,
        SO_SNDTIMEO,
        (char *)&timeout,
        sizeof(timeout));
if (err != NO_ERROR) {
    /* failed for some reason... */
}
The TIMEOUT_VALUE is the needed time-out in milliseconds. To set a receive time-out, substitute SO_RCVTIMEO for SO_SNDTIMEO in the preceding example.


0
 

Author Comment

by:acbirdie
Comment Utility
I already know how to do a send timeout.  I am talking about establishing a connection using the connect() command.  I want it to timeout if a connection after a certain amount of time cannot be made.
0
 
LVL 48

Expert Comment

by:AlexFM
Comment Utility
Call WSAEventSelect with FD_CONNECT flag. After this call connect - it returns immidiately. Call WSAWaitForMultipleEvents with event from WSAEventSelect specifying required timeout. If WSAWaitForMultipleEvents succeeded, use WSAEnumNetworkEvents to identify what network event occured.

You can see the way implemented in the client application from this article:

http://www.codeproject.com/internet/winsockiocp.asp
0
 

Author Comment

by:acbirdie
Comment Utility
           if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
            {
                  errCode = ERR_SOCK_FAILED;
                  sockErr = WSAGetLastError();
                  break;
            }

      memset(&sServAddr, 0, sizeof(sServAddr));        /* Zero out structure */
            sServAddr.sin_family      = AF_INET;             /* Internet address family */
            sServAddr.sin_addr.s_addr = inet_addr(hostIp);   /* Server IP address */
            sServAddr.sin_port        = htons(hostPort);     /* Server port */

            // Create an even handler
            WSAEVENT WSACreateEvent(void);
            // Connect using primary IP and port number
            if (connect(sock, (struct sockaddr *) &sServAddr, sizeof(sServAddr)) == SOCKET_ERROR)
            {
                  hostIp = cfg_sec_host_serv;
                  convertPort = strtol(cfg_sec_host_port, (char**) NULL, 10);
                  hostPort = convertPort;

                  memset(&sServAddr, 0, sizeof(sServAddr));       /* Zero out structure */
                  sServAddr.sin_family      = AF_INET;            /* Internet address family */
                  sServAddr.sin_addr.s_addr = inet_addr(hostIp);  /* Server IP address */
                  sServAddr.sin_port        = htons(hostPort);    /* Server port */

                  // Connect using second IP and port number
0
 

Author Comment

by:acbirdie
Comment Utility
AlexFm

Okay, sorry I accidently posted the code without explaining it.  Anyways, ignore the WSAEVENT I was trying to figure out how to do it my self and was getting confused.

Basically I set the address and port info and try to connect. then when the connection fail I try an alternative IP address and port, then I try a third one and give up if cannt connect.  I am a bit confused on how to incorporate your suggestions into my current code.  Can you help me understand.
0
 
LVL 48

Accepted Solution

by:
AlexFM earned 450 total points
Comment Utility
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if ( sock == INVALID_SOCKET )
{
    // error
}

SOCKADDR_IN sServAddr;
// fill sServAddr ...

// connect asynchronously (non-blocking call)
int nRet = connect(sock ,(sockaddr*)&sServAddr, sizeof(sServAddr));

if (nRet == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
{
    // error
}

WSAEVENT hEvent = WSACreateEvent();
if ( hEvent == WSA_INVALID_EVENT )
{
  // error
}

// Ask event notification when socket will be connected
nRet = WSAEventSelect(sock,
        hEvent,
        FD_CONNECT);             // add here another flags for futher processing

if (nRet == SOCKET_ERROR)
{
    // error
}

// wait for connection
DWORD dwRet = WSAWaitForMultipleEvents(1,
            &hEvent ,
            FALSE,
            5000,                     // timeout 5 sec
            FALSE);
   
if (dwRet == WSA_WAIT_TIMEOUT)
{
     // no connection in specified time - add here your handling
}

WSANETWORKEVENTS events;
nRet = WSAEnumNetworkEvents(socket,
            hEvent,
            &events);

if (nRet == SOCKET_ERROR )
{
    // error
}

if ( events.lNetworkEvents & FD_CONNECT )
{
    // connection signaled
    if ( events.iErrorCodes[FD_CONNECT_BIT] != 0 )
    {
        // error
    }

    // connection to server is successful
}

}
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Author Comment

by:acbirdie
Comment Utility
AlexFM,

I know I will have to do a WSACloseEvent once I am through with everything.  The question I have is do I have to create a new event for each time I attempt to connect to a different IP address if one fails.

acbirdie
0
 
LVL 48

Expert Comment

by:AlexFM
Comment Utility
No, just reset it:

WSAResetEvent(hEvent );
0
 

Author Comment

by:acbirdie
Comment Utility
I have another question.  Before, once I made a connect I would send something then wait to recv something.  Well now I am not receiving anything.  I get an 10035 error.  When I check the computer that is trying to send something back to me they are saying my socket is closed.  How can I  send and receive info once I establish a connection.

// Set timeout value for receive
if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&nTimeout, sizeof(int)) == SOCKET_ERROR)
{
      errCode = ERR_SET_TIME_OUT_FAILED;
      sockErr = WSAGetLastError();
      break;
}
// Send message to server
if ((send(sock, szMessage, strlen(szMessage), 0)) != strlen(szMessage))
{
      errCode = ERR_SEND_FAILED;
      sockErr = WSAGetLastError();
      break;
}

// Attempt to receive message
do
{
      if ((byteRcvd = recv(sock, recvBuffer, 1, 0)) <= 0)
      {
            errCode = ERR_RECV_FAILED;
            sockErr = WSAGetLastError();
            break;
      }
      totalRcvd += byteRcvd;
      os << recvBuffer[0];
} while (recvBuffer[0] != '~');
os << '\0';
            
      
0
 

Author Comment

by:acbirdie
Comment Utility
Okay,

Well my code works in debug mode but not in release mode.  So I have to figure out what's goin on.  I do have another question.  Does WSACloseEvent take care of WSAWaitForMultipleEvents and WSAEnumNetworkEvents calls too?
0
 

Author Comment

by:acbirdie
Comment Utility
AlexFM,

Help.  The WSAEWOULDBLOCK is my problem.  I am just allittle confused.  I am able to send the data but not receive it.  What I think is going on is the recv is not ready to get data from the server which is why I am.  If I am right, How can I make sure that the recv and even the send is ready to receive or send data through the socket.  If I am wrong please help me anyways.
0
 
LVL 48

Expert Comment

by:AlexFM
Comment Utility
Please read the client project from this article:

http://www.codeproject.com/internet/winsockiocp.asp

Server project is complicated, but client is relatively simple. It shows how to handle socket events asynchronously, by the same way as it is connected in my code fragment. Any socket call (connect, recv, send...) is by default asynchronous. This means, it returns immidiately with WSAEWOULDBLOCK code. When operation is really completed, event from WSAEventSelect call is signaled. Program waiting for this event in WSAWaitForMultipleEvents wakes up and handles this event.

WSAWOULDBLOCK means: this call would block if socket was blocking. However, socket is non-blocking, function returns immidiately and you should wait for actual completion of socket I/O operation by some way (for example, waiting for event).
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now