15

UNIXでは、すべてが関数のファイルアプローチです。 は、Win32 ではサポートされていません。read()write()close()

私はそれをエミュレートしたいのですが、WinSocks2sockソケットまたはfdを区別する方法がわかりません。

//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

4 に答える 4

10

Socket HandlesページSOCKETで明確に述べられているように、Windows がハンドルをファイルとして使用することを許可していないという考えがどこにあるのかわかりません。

ソケット ハンドルは、必要に応じて Windows Sockets 2 のファイル ハンドルにすることができます。Winsock プロバイダーのソケット ハンドルは、ReadFile、WriteFile、ReadFileEx、WriteFileEx などの他の非 Winsock 関数で使用できます。

とにかく、Windows でそれらを区別する方法については、関数NtQueryObject\Device\Tcpを参照してください。これは、渡されたハンドルが openの場合にハンドル名を返しますSOCKET。この呼び出しによって返される構造については、「備考」セクションを参照してください。

このアプローチは XP 以降でのみ機能し、Windows 2000 では失敗することに注意してください (Windows 2000 は十分に古いため、影響はないと思います)。

于 2011-07-04T18:24:46.200 に答える
5

select を使用してソケットのステータスを照会できると思います。

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

ファイル記述子とソケットを単一の構造体にグループ化することをお勧めします。記述子がファイルまたはソケットであるかどうかを示す列挙型を宣言できます。これはあなたが望むほど動的ではないかもしれませんが、一般的に、移植可能なアプリケーションを作成するときは、それらの詳細を抽象化するのが最善です.

例:

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
}
于 2011-07-04T12:41:28.177 に答える
3

Windows 'C' ライブラリに dup() がある場合は、dup を試みることができます。これはソケットでは失敗しますが、ファイル fd では成功します。そう:

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

警告: テストされていない依存関係を持つテストされていない理論 ;-) fd を使い果たした場合、誤解を招く結果が返されることに注意してください。もう 1 つの副作用は、ファイルの場合はフラッシュされ、そのディレクトリ エントリが更新されることです。全体として、おそらく率直に言って最悪です。私自身も反対票を投じるかもしれません。

于 2011-06-24T07:03:34.710 に答える
3

私は推測しています...しかし、Windowsのfdsとソケットは別々の名前空間を使用しているとは思いません。したがって、ソケットとファイルの番号が同じである可能性があり、 を呼び出したときにどちらについて話しているかを知ることは不可能ですis_net_socket

ソケット番号と fd 番号を出力してみて、それらが同時に互いに同じかどうかを確認してください。

于 2011-06-23T22:47:12.413 に答える