在unix上, 一切都是函数read()
, write()
, close()
在Win32上不支持的文件方法。
我想模拟它,但不知道如何区分sock
是在WinSocks2上的套接字或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 }
不知道你在哪里得到的想法,Windows不会允许你使用SOCKET
句柄作为文件 – 正如在Socket处理页面清楚说明:
套接字句柄可以选择性地作为Windows套接字2中的文件句柄。来自Winsock提供程序的套接字句柄可以与其他非Winsock函数(如ReadFile,WriteFile,ReadFileEx和WriteFileEx)一起使用。
无论如何,至于如何在Windows上区分它们,请参阅函数NtQueryObject ,如果传递给它的句柄是一个开放的SOCKET
,它将返回句柄名称\Device\Tcp
。 阅读这个调用返回的结构的“备注”部分。
请注意,这种方法只适用于XP和以上,并将在Windows 2000上失败(我认为这是足够老,它不会影响你。)
我想你可以使用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 }
我怀疑…但我不确定,Windows上的fds和套接字使用单独的名称空间。 因此,一个套接字和一个文件的编号可能是相同的,当调用is_net_socket
时候,不可能知道你在说什么。
尝试打印出套接字和fd号码,看看他们是否在同一时间相同。
如果Windows的'C'库有dup(),你可以尝试重复它,这将失败的套接字,但成功的文件fd。 所以:
int is_net_socket(fd) { return close(dup(fd)) != 0; }
警告:未经测试的依赖关系理论未经检验;-)请注意,这将返回误导的结果,如果你用完fd的。 另一个副作用是,如果它是一个文件,它将被刷新,并更新其目录条目。 总而言之,这可能是非常糟糕的。 我甚至可以自己冷静下来。