在socket和fd之间确定

时间:2011-06-23 22:12:03

标签: c windows sockets winsock winsock2

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

我想模仿它但不知道如何区分WinSocks2上sock socket 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 个答案:

答案 0 :(得分:10)

不确定您认为Windows不允许您将SOCKET句柄用作文件的位置 - 正如Socket Handles页面上明确说明的那样:

  

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

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

请注意,此方法仅适用于XP及以上版本,并且在Windows 2000上会失败(我假设它已经足够大,不会对您产生影响。)

答案 1 :(得分: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
}

答案 2 :(得分:3)

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

尝试打印出socket和fd号码,看看它们是否在同一时间彼此相同。

答案 3 :(得分:3)

如果Windows“C”库有dup(),你可以尝试复制它,这对于套接字来说应该是失败但是对于文件fd是成功的。所以:

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

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