Link to home
Create AccountLog in
Avatar of int_acct
int_acct

asked on

Socket Error - how to make it appear out fast?

ermz..i have a problem here... i want to connect a server-client application to a wireless LAN device thru sockets. But when the other device is not found, an error 10051 or something like that appears.

Rite now that error appears out after 2 mins or so .I need the error to appear out faster. Is there any way for me to do it?
Avatar of novitiate
novitiate

you can set the SO_SNDTIMEO and SO_RCVTIMEO options with setsockopt() to change the timeouts for send() and recv().

Refer: http://tangentsoft.net/wskfaq/newbie.html#timeout

_novi_
How long does it take if it succeeds? Some seconds?

You could do the following:

- set the socket to non-blocking before connect
- call connect
- the call immediately returns with SOCKET_ERROR and WSAE_WOULDBLOCK
- after that you have to use select function to check whether the socket is
  writeable (connection succeeded) or not.
- the select function may called using an appropriate  timeout  value.

Regards, Alex
Avatar of int_acct

ASKER

ermz...i want it to fail... and i want the failure to come out faster... could i have some sample codes plz? i have totally no idea as to how to how to do it...

   

    // set the socket to nonblocking
    unsigned long argp = 1;
    ioctlsocket (socket, FIONBIO, &argp);

    unsigned long ipHost  = inet_addr("192.168.0.1");
    UShort          portNo  = 51239;
    struct sockaddr_in host;
    // fill awsome sockaddr_in structure
    memset (&host, 0, sizeof (host));              // set all zero    
    host.sin_family      = AF_INET;                  // the only family supported
    host.sin_port        = htons(portNo);           // host order to network order
    host.sin_addr.s_addr = ipHost;                 // that is big endian
   
    int result = 0;
    // connect to socket fails because of non-blocking socket
    if ((result = connect(sock, (struct sockaddr*) &host, sizeof(host))) < 0)
    {
        // fd_set manages an array of sockets
       fd_set          writeSockets;
       struct timeval  tval;

        // set host socket as first and only element
        FD_ZERO(&writeSockets);
        FD_SET(sockHost, &writeSockets);
        // init timeout
        tval.tv_sec  = 2;   // wait 2 seconds
        tval.tv_usec = 0;
        result = select(sockHost + 1, NULL; &writeSockets, NULL, &tval);
        if (result == 0)
             return 1;   // timeout, the socket was not writeable within timeout
        else if (result == SOCKET_ERROR)
             return 2;   // socket error
       
        // if come here the connection succeeded

...


Regards, Alex
ermz.... sorry i meant i needed the sample codes for setsockopt() to change the timeouts for send() and recv().  sorry sorry...
>>>> ermz....

who is ermz?

>>>> i needed the sample codes for setsockopt() to change the timeouts for send() and recv()

changing sending/receiving timeouts doesn't help for connection. The connection timeouts are with your tcp/ip subsystem and must be configured there.

The method I told you above doesn't speed up connection but gives your prog control while the connection is in progress. So, if for example there is no connection after 10 seconds, you may decide that the device isn't available.

Regards, Alex
oh ok..sorry abt that Alex... so should i implement this on the server side or the client side? i want the error message to appear on the server side... and where should i implement this? i mean...which part of the server codes should i add this in?
>>>> i want to connect a server-client application to a wireless LAN

If your initial requirement still is valid ... of course it is a client connect. When the server opens, binds and listens to a socket, WLAN isn't involved. The local TCP/IP subsystem should be valid with or without WLAN device, except that the WLAN device works as a DHCP server. In the latter case your system gets a valid IP address from the device, ergo, no device no IP address.

What is the IP address/port your server binds and listens to? It must be the same the clients are using to connect. Is it always valid, could you make a ping on it? Or are you using 127.0.0.1 ?

>>>> should i implement this on the server side or the client side?

the code snippet is for a client connect. You can use it to prevent your clients from *hanging* if the WLAN device isn't available or working. By making a socket non-blocking all requests to a socket - connect/recv/accept/disconnect ... immediately return to the caller - it doesn't hang. However, the requests rarely succeed but return with socket error and error code WSAE_WOULDBLOCK, indicating that the call wasn't finished. You either have to poll your request, e. g. recv, or use functions like select() that give information about the status of the socket. If - for example - the connect finally succeeds, the socket status asynchronously turns to writeable. So, if a call to select finds out that the socket is writeable, you know that the inital connect was finished. The benefit of this method is that select can be called with timeout. So, if you want to wait 5 seconds but not more, you can do that by using select.

For the server site the odds are different. A server binds and listens to a server socket. The only dependence on a WLAN device could be if the device acts as DHCP server. But, if the WLAN doesn't work, your server has nothing to serve. So it seems that it doesn't matter whether it hangs on a missing WLAN-Device or not. After listen the server calls accept() in order to accept connecting clients. The accept call is going to hang if the socket is blocking. You can avoid this by setting the socket to non-blocking as described above. Then, you have to poll the socket in order to accept incoming connections. Or you check the read status of your socket using select with timeout. In both cases you keep control of your program and be able to exit, e. g. on user request.

If your server connects to a second server, it is a client for that purpose. So, you may use the code snippet from above tor prevent from hanging.

Regards, Alex
   
Oh I see...so does that mean that if i use the codes that u have given me, it would result in the socket not being to connect most of the time?
These are my codes...how do i do it...

      void servSocket::PrepSend()
      {
            
            //      CString ippp = takeoutIP("DoorBellIp");
            
            //      char* p = ( LPCTSTR) ippp; //uses CString::operator ( LPCTSTR);
            //char p[16];
            //p = ippp.GetBuffer(0);
            
            
            // Initialize Winsocket.
            if (WSAStartup (MAKEWORD(1,1), &sendWSAData) != 0)
            {
                  wsprintf (szSendError, TEXT("WSAStartup failed. Error: %d"),
                        WSAGetLastError ());
                  MessageBox (NULL, szSendError,NULL, MB_OK);
            }
            
            // Create a TCP/IP socket that is bound to the server.
            if ((ServerSendSock = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
            {
                  wsprintf (szSendError, TEXT("Allocating socket failed. Error: %d"),
                        WSAGetLastError ());
                  MessageBox (NULL, szSendError,NULL, MB_OK);
                  
            }
            
            // Fill out the server socket's address information.
            send_destination_sin.sin_family = AF_INET;
            
            // Retrieve the host information corresponding to the host name.
            if ((sendPhostent = gethostbyname (HOSTNAME)) == NULL)
            {
                  wsprintf (szSendError, TEXT("Unable to get the host name. Error: %d"),
                        WSAGetLastError ());
                  MessageBox (NULL, szSendError,NULL, MB_OK);
                  closesocket (ServerSendSock);
            }
            
            // Assign the socket IP address.
            memcpy ((char FAR *)&(send_destination_sin.sin_addr),
                  sendPhostent->h_addr,
                  sendPhostent->h_length);
            
            // Convert to network ordering.
            
            send_destination_sin.sin_port = htons (PCLISTEN);
            
            // Convert into char
            char ipAddr[16];
            int ipLength=0;
            CString m_ServerIP;
            
            
            m_ServerIP =       "192.168.0.15";
            ipLength = m_ServerIP.GetLength();
            if(ipLength != 0)
            {
                  
                  for(int i=0;i<ipLength;i++) {
                        ipAddr[i] = (char)m_ServerIP.GetAt(i);
                  }
                  ipAddr[i] = '\0';
            }
            else
            {
                  MessageBox (NULL,_T("Enter IP Address"), NULL,MB_OK);
            }
            
            send_destination_sin.sin_addr.s_addr = inet_addr(ipAddr);
            
            // Establish a connection to the server socket.
            if (connect (ServerSendSock,
                  (PSOCKADDR) &send_destination_sin,
                        sizeof (send_destination_sin)) == SOCKET_ERROR)
            {
                  wsprintf (szSendError,TEXT("Connecting to the server failed. Error: %d"),
                        WSAGetLastError ());
                  MessageBox (NULL, szSendError + (CString)"\nPlease check if u registered the PDA",NULL, MB_OK);
                  closesocket (ServerSendSock);
            }
            
      }
>>>> it would result in the socket not being to connect most of the time

No, the result is only, that the connect call returns immediately and you don't have to wait until the connection actually is done.

>>>> These are my codes...how do i do it...

You seem to mixup server and client in your code...

By using gethostbyname you normally set-up a server socket that would bind and listen and finally calls accept to be able to accept clients that try to connect to your server.  However, you actually don't use the information received by gethostbyname but init a new struct host for IP 192.168.0.15 which obviously is a different server. So your program turns to a client and tries to connect to a different server.

BTW,  the code sequence

          // Convert into char
          char ipAddr[16];
          int ipLength=0;
          CString m_ServerIP;
         
         
          m_ServerIP =      "192.168.0.15";
          ipLength = m_ServerIP.GetLength();
          if(ipLength != 0)
          {
               
               for(int i=0;i<ipLength;i++) {
                    ipAddr[i] = (char)m_ServerIP.GetAt(i);
               }
               ipAddr[i] = '\0';
          }
          else
          {
               MessageBox (NULL,_T("Enter IP Address"), NULL,MB_OK);
          }
         
can be replaced by that single statement.

   char ipAddr[] = "192.168.0.15";


>>>> Where to set the socket to non-blocking?

Directly before the connect. Your code would change to

        // set the socket to nonblocking
        unsigned long argp = 1;
        ioctlsocket (ServerSendSock, FIONBIO, &argp);

          // Establish a connection to the server socket.
          int rc;
          if ((rc = connect (ServerSendSock,
               (PSOCKADDR) &send_destination_sin,
                    sizeof (send_destination_sin))) == SOCKET_ERROR)
          {
               unsigned err = WSAGetLastError ();
               if (err != WSAE_WOULDBLOCK)
               {
                    wsprintf (szSendError,TEXT("Connecting to the server failed. Error: %d"),
                    WSAGetLastError ());
                    MessageBox (NULL, szSendError + (CString)"\nPlease check if u registered the PDA",NULL, MB_OK);
                    closesocket (ServerSendSock);
                    return;
                }

                // fd_set manages an array of sockets
                fd_set          writeSockets;
                struct timeval  tval;

                // set host socket as first and only element
                FD_ZERO(&writeSockets);
                FD_SET(ServerSendSock, &writeSockets);
                // init timeout
                tval.tv_sec  = 2;   // wait 2 seconds
                tval.tv_usec = 0;
                result = select(ServerSendSock + 1, NULL; &writeSockets, NULL, &tval);
                if (result == 0)
                {
                       MessageBox (NULL, szSendError + (CString)"\nConnection failled to succeed within timeout.",NULL, MB_OK);
                       return;   // timeout, the socket was not writeable within timeout
                }
                else if (result == SOCKET_ERROR)
                {
                        wsprintf (szSendError,TEXT("Connecting to the server failed. Error: %d"),
                        WSAGetLastError ());
                        MessageBox (NULL, szSendError + (CString)"\nPlease check if u registered the PDA",NULL, MB_OK);
                        closesocket (ServerSendSock);
                        return;   // socket error
                 }

                 // if come here the connection succeeded

          }
         
     }



Regards, Alex





It says that WASE_NONBLOCKING : undeclared error...
and result undeclared indentified error too...
ASKER CERTIFIED SOLUTION
Avatar of itsmeandnobodyelse
itsmeandnobodyelse
Flag of Germany image

Link to home
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
See answer