Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine between socket and fd

On unix everything is a file approach of function read(), write(), close() is not supported on Win32.

I want to emulate it but have no idea how to distinguish when sock is socket or fd on WinSocks2.

//returns 1 if `sock` is network socket, 
//        0 if `sock` is file desriptor (including stdio, stderr, stdout), ...
//       -1 in none of above
int is_net_socket(int sock)
{
    // ...?
}

This should work as in :

int mysock  = socket(PF_INET, SOCK_STREAM, 0);
int myfd    = _open("my_file.txt", _O_RDONLY);

printf("1: %d    2: %d    3: %d    4:%d\n",
       is_net_socket(mysock),   //1
       is_net_socket(myfd),     //0
       is_net_socket(stdin),    //0
       is_net_socket(stderr));  //0

// should print "1: 1    2: 0    3: 0    4:0"

How to implement is_net_socket in order to use it as in:

int my_close(int sock)
{
#if ON_WINDOWS
    switch( is_net_socket(sock) ) {
        case 1: return closesocket(sock);
        case 0: return _close(sock);
        default: //handle error...
    }
#else
    return close(sock);
#endif
}
like image 224
DinGODzilla Avatar asked Jun 23 '11 22:06

DinGODzilla


2 Answers

Not sure where you're getting the idea that Windows won't allow you to use SOCKET handles as files - as clearly stated on the Socket Handles page:

A socket handle can optionally be a file handle in Windows Sockets 2. A socket handle from a Winsock provider can be used with other non-Winsock functions such as ReadFile, WriteFile, ReadFileEx, and WriteFileEx.

Anyways, as to how to distinguish between them on Windows, see the function NtQueryObject, which will return a handle name of \Device\Tcp if the handle passed to it is an open SOCKET. Read the "Remarks" section for the structure returned by this call.

Note that this approach only works XP and up, and will fail on Windows 2000 (which I'm assuming is old enough that it doesn't affect you.)

like image 121
TkTech Avatar answered Oct 04 '22 13:10

TkTech


I suppose you can use select to query the status of a socket.

http://msdn.microsoft.com/en-us/library/ms740141%28VS.85%29.aspx

I would recommend grouping your file desc and sockets in a single struct. You can declare an enum to tell if the descriptor is a file or socket. I know this might not be as dynamic as you want, but generally when you create portable applications, its best to abstract those details away.

Example:

enum type { SOCKET, FILE };

typedef struct
{
    unsigned int id;
    type dataType;
} descriptor_t;

int close(descriptor_t sock)
{
#if WIN32
    if (sock.dataType == SOCKET)
        return closesocket(sock.id);
    else
        return _close(sock.id);
#else
    return close(sock.id);
#endif
}
like image 29
Sophy Pal Avatar answered Oct 04 '22 15:10

Sophy Pal