You are here

TutorialLibraryTest ApplicationDownload
[Tutorial]LibraryTest ApplicationDownload

Socket Tutorial

Chapter 10 - Connection Request

C_SCP::Connect (int waitTime, char* addr, unsigned int port, unsigned int *pIDLink)

This function attempts to connect to a server at the specified address (addr and port) within a given time frame (parameter waittime). A negative value of this parameter means function can potentially wait infinitely (blocking mode), while value 0 means function performs a query and returns immediately (non-blocking mode). If successful, a new socket is created and the link identifier is written to parameter pIDLink. This is not the the new socket identifier (which is hidden), but rather a value to use with other library functions to identify the link.

Along with the local variables declaration, the time at which the user enters the function (t1) is stored.

S_Error error;
unsigned long arg;
struct sockaddr_in sa;
struct hostent *hp;
int result;
int sock;
unsigned int t1, t2;

t1 = GetTime_tick ();

Then, network information about the machine we want to connect to are gathered in structure hp thanks to function gethostbyname. Then, sa address is built according to these network information. Address (sa.sin_addr) and address type (sa.sin_family) are extracted from structure hp. The port on which to connect is also specified (sa.sin_port).

// info about server we want to connect to
hp = gethostbyname (addr);

	(...)
	
// Connection parameters
memset (&sa, 0, sizeof (sockaddr_in));

memcpy ((char*) &sa.sin_addr, hp->h_addr, hp->h_length);
sa.sin_family = hp->h_addrtype;
sa.sin_port = htons (port);

An IP socket v4 bound to TCP protocol is then created by a call to socket. In contrast to what is done elsewhere in this library, we put this socket in blocking mode. This approach allows us to know if the connection request is successful as soon as the call returns. In principle it does not block for a long time, even in case of failure. However, be aware that with this implementation, our function can block longer than requested by parameter waittime.

sock = socket (AF_INET, SOCK_STREAM, 0);
	
(...)

// Blocking mode
result = Sock_SetBlockMode (sock, true);

The final step is to loop through function connect until it succeeds or until our time frame expires (waittime). Here we can not work with function select because a client has no way of knowing whether a call to connect will succeed or not. Indeed, there is no exchange of information with the server until the client is connected, which is the purpose of this function. So we must make attempts at regular intervals. The delay between each attempts here is 100ms. Making queries faster doesn't bring much. <=1.

// Connection (every 100ms try)
do
{
   result = connect (sock, (struct sockaddr*) &sa, sizeof (sa));

   if (result == SOCKET_ERROR)
   {
      t2 = GetTime_tick ();

      // Check time left
      if (waitTime >= 0 && (unsigned int) waitTime <= (t2 - t1))
      {
         (...)
		
         closesocket (sock);
         return error;
      }
   }
   else break;

   // Sleeping for 100 ms
   #if (SOCK_CONTEXT == CTX_WIN32NT)	
      Sleep (100);
   #elif (SOCK_CONTEXT == CTX_LINUX)
      usleep (100000);
   #endif
}
while (true);