15

在 unix 上,一切都是函数的文件方法,read()Win32不支持。write()close()

我想模仿它,但不知道如何区分WinSocks2sock上的socketfd

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

不确定您从哪里得到 Windows 不允许您将SOCKET句柄用作文件的想法 - 正如Socket Handles页面上明确说明的那样:

套接字句柄可以是 Windows 套接字 2 中的文件句柄。来自 Winsock 提供程序的套接字句柄可以与其他非 Winsock 函数一起使用,例如 ReadFile、WriteFile、ReadFileEx 和 WriteFileEx。

无论如何,关于如何在 Windows 上区分它们,请参见函数NtQueryObject\Device\Tcp ,如果传递给它的句柄是 open ,它将返回句柄名称SOCKET。阅读此调用返回的结构的“备注”部分。

请注意,这种方法仅适用于 XP 及更高版本,并且在 Windows 2000 上会失败(我假设它已经足够老了,不会影响您。)

于 2011-07-04T18:24:46.200 回答
5

我想您可以使用 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
}
于 2011-07-04T12:41:28.177 回答
3

如果 Windows 'C' 库有 dup() 你可以尝试 dup 它,对于套接字应该会失败,但对于文件 fd 会成功。所以:

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

警告:未经测试的理论具有未经测试的依赖性;-) 请注意,如果您用完 fd,这将返回误导性结果。另一个副作用是,如果它是一个文件,它将被刷新并更新其目录条目。总而言之,坦率地说,它可能很糟糕。我什至可能自己投反对票。

于 2011-06-24T07:03:34.710 回答
3

我怀疑......但我不确定 Windows 上的 fds 和套接字使用单独的命名空间。因此,一个套接字和一个文件的编号可能相同,并且在调用时无法知道您在谈论哪个is_net_socket

尝试打印出套接字和 fd 编号,看看它们是否同时彼此相同。

于 2011-06-23T22:47:12.413 回答