You are here

TutorialLibraryTest ApplicationDownload
[Tutorial]LibraryTest ApplicationDownload

Error message

Deprecated function: The each() function is deprecated. This message will be suppressed on further calls in menu_set_active_trail() (line 2404 of /home/quantics/public_html/dp/includes/menu.inc).

Socket Tutorial

Chapter 11 - Writing Data

C_Sockets::Write (unsigned int ID, unsigned int IDlink, unsigned char *pData, int *pLength, int waitTime_ms)

This function attempts to write pLength Bytes of data from buffer pData on a socket. This socket is identified by parameter ID specifying an object C_SCP, and by the parameter IDlink indicating which socket link to use. Parameter waitTime_ms specifies the maximum time frame, in milliseconds, this operation can last. A negative value means function can potentially wait infinitely (blocking mode), while value 0 means function make one trial and returns immediately (non-blocking mode).

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

SockError er;
int error;
unsigned int idx;
unsigned long arg;
unsigned int numWrite, t1, t2;
int sockWrite;
int result;
timeval tv;
fd_set fdset;

t1 = GetTime_tick ();

Socket identified by the parameters ID and IDlink is put in non-blocking mode.

// Non-blocking mode
result = Sock_SetBlockMode (sockWrite, false);

if (result != 0) 
{
   (...)
   return er;
}

The main loop of this function attempts to write data from buffer pData on the socket. Parameter numWrite stores the number of bytes already sent (0 initially). If successful, the number of data actually sent is taken into account (incrementation of pData and numWrite).

// Sending data loop
numWrite = 0;

do
{
   result = send (sockWrite, (char*) pData, *pLength - numWrite, 0);
		
   (...)
   // Data have been taken into account
   if (result > 0)
   {
      pData += result;
      numWrite += result;
   }

If error WOULD BLOCK occurs, it means that the socket's internal buffers are full and that the operation can not be achieved without blocking (the socket is non-blocking). In this case, remaining time is calculated (t2 - t1) and function selec" is called again, waiting for socket to become writeable again. If there is more time, the function returns.

// No data sent because internal buffer is full
else if (error == WSAEWOULDBLOCK)
{
   t2 = GetTime_tick ();

   // Time expired
   if (waitTime_ms >= 0 && (unsigned int) waitTime_ms <= (t2 - t1))
   {
      break;
   }

   // Wait for new room in the internal socket buffer
   FD_ZERO (&fdset);
   FD_SET (sockWrite, &fdset);

   if (waitTime_ms >= 0) 
   {
      if ((unsigned int) waitTime_ms > (t2-t1))
      {
         tv.tv_sec = (waitTime_ms  - (t2-t1) ) / 1000;
         tv.tv_usec = ( (waitTime_ms - (t2-t1))  % 1000) * 1000;
      }
      else
      {
         tv.tv_sec = 0;
         tv.tv_usec = 0;
      }
      result = select (sockWrite +1, NULL, &fdset, NULL, &tv);
   }
   else
      result = select (sockWrite +1, NULL, &fdset, NULL, NULL);

   // Time expired
   if (result == 0) 
   {
      break;
   }
   // Error
   if (result == SOCKET_ERROR )
   {
      (...)
				
      break;
   }
}

As long as there is no error and there is time left, loop continues until all data have been written.

   (...)
}
while (numWrite < (unsigned int) *pLength);