Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

equivalent of TIOCOUTQ / SIOCOUTQ in windows

Till date my googling and checking out of msdn suggests Microsoft Windows does not offer any equivalent of TIOCOUTQ / SIOCOUTQ to find the amount of unsent data in the socket send buffer. It will be so useful if some good hack discovered something otherwise, and could post it here. It will allow my following code to become cross-platform

int net_get_unsent (const int sockfd, unsigned long &sock_bytes_unsent )
{

/*  Queries how much data sent on sockfd, 
 *  may not have yet been recieved by the reciever
 * 
 *  returns more than 1 if there's unsent data,
 *  and fills in the amount of unsent data in sock_bytes_unsent
 * 
 * returns 0 if all the data has been sent
 * 
 * returns < 0 if there was a socket I/O error 
 * */

    int err = 0;
    int wsaerr = 0;

    if (sockfd <= 0)
        return -1;

#ifdef WINDOWS
    err = ioctlsocket(sockfd, SIOCOUTQ , &sock_bytes_unsent);

#else
    err = ioctl(sockfd, TIOCOUTQ, &sock_bytes_unsent);

#endif
    if (err < 0) {

#ifdef WINDOWS  
        wsaerr = WSAGetLastError();
#else
        wsaerr = errno;
#endif      
        printf("failed to get unsent data error:%d", wsaerr );
        sock_bytes_unsent = 0;
        return -1 * wsaerr;

    } else if (sock_bytes_unsent > 0 ) {
        printf( "unsent data: %lu bytes", sock_bytes_unsent );
        return 1;
    }

    return err;
}
like image 983
mdk Avatar asked Nov 13 '22 20:11

mdk


2 Answers

As far as I know there isn't such a call in Windows. (A pity since it works very well!)

However, the following link I've found to be extremely useful and may help you solve your problem. The concepts are for any OS except obviously the SIOCOUTQ part mentioned in the "What else can be done?" section.

The ultimate so_linger page or why is my tcp not reliable

like image 75
hookenz Avatar answered Nov 15 '22 11:11

hookenz


Adding on Pavel P comment, I can confirm it is deadlocking. Fix for the depleteSendBuffer func (linux version):

/*!\fn int depleteSendBuffer ( int fd , long timeout )
 *\brief wait until the socket is empty or timeout, checking each 50 msec
 *\param fd socket descriptor
 *\timeout timeout value in msec 
 *\return TRUE of FALSE 
 */
int depleteSendBuffer ( int fd , long timeout )
{
    int done = FALSE ;
    int lastOutstanding=-1;
    timeout /= 50 ;
    for( int it = 0 ; it < timeout ; it += 50 )
    {
        int outstanding;
        ioctl(fd, SIOCOUTQ, &outstanding);
        if(outstanding != lastOutstanding)
            printf("Outstanding: %d\n", outstanding);
        lastOutstanding = outstanding;
        if(!outstanding)
        {
            done = TRUE ;
            break;
        }
        usleep( 50000 );
    }
    return done ;
}
like image 21
Gull_Code Avatar answered Nov 15 '22 12:11

Gull_Code