Определить между сокетом и FD - PullRequest
15 голосов
/ 24 июня 2011

В Unix все является файлом приближение функции read(), write(), close() не поддерживается в Win32.

Я хочуэмулируйте его, но не знаете, как определить, когда sock это socket или fd на 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)
{
    // ...?
}

Это должно работать так:

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"

Как реализовать is_net_socket, чтобы использовать его как:

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
}

Ответы [ 4 ]

10 голосов
/ 04 июля 2011

Не уверен, откуда вы взяли, что Windows не позволит вам использовать SOCKET дескрипторы в качестве файлов - как четко указано на странице Socket Handles :

Дескриптор сокета может дополнительно быть дескриптором файла в Windows Sockets 2. Дескриптор сокета от поставщика Winsock может использоваться с другими функциями, не относящимися к Winsock, такими как ReadFile, WriteFile, ReadFileEx и WriteFileEx.

В любом случае, что касается , как различать их в Windows, см. Функцию NtQueryObject , которая будет возвращать имя дескриптора \Device\Tcp, если переданный ему дескриптор является открытымSOCKET.Прочитайте раздел «Замечания» для структуры, возвращаемой этим вызовом.

Обратите внимание, что этот подход работает только на XP и более поздних версиях и потерпит неудачу в Windows 2000 (я полагаю, он достаточно старый, чтобы этого не делатьповлиять на вас.)

5 голосов
/ 04 июля 2011

Полагаю, вы можете использовать select для запроса статуса сокета.

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

Я бы порекомендовал сгруппировать ваш файл desc и сокеты в одну структуру.Вы можете объявить перечисление, чтобы сказать, является ли дескриптор файлом или сокетом.Я знаю, что это может быть не так динамично, как вы хотите, но обычно при создании переносимых приложений лучше абстрагировать эти детали.

Пример:

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
}
3 голосов
/ 24 июня 2011

Если в библиотеке Windows 'C' есть функция dup (), вы можете попытаться ее дублировать, что должно произойти с ошибкой для сокета, но успешно для файла fd. Итак:

int is_net_socket(fd)
{
  return close(dup(fd)) != 0;
}

Предупреждение: непроверенная теория с непроверенной зависимостью ;-) Обратите внимание, что это даст неверные результаты, если у вас закончатся fd. Другой побочный эффект заключается в том, что если это файл, он будет очищен и его запись в каталоге обновлена. В целом это, вероятно, отстой откровенно. Я мог бы даже понизить это сам.

3 голосов
/ 24 июня 2011

Подозреваю ... но я не уверен, что fds и сокеты в Windows используют отдельные пространства имен. Поэтому номер сокета и файла может совпадать, и невозможно узнать, о каком вы говорите, когда звоните is_net_socket.

Попробуйте распечатать номера сокетов и fd, чтобы узнать, совпадают ли они друг с другом одновременно.

...