2011-06-23 34 views
15

在Unix 一切文件的功能read()write()方法,close()不支持在Win32。確定和FD

我想效仿,但不知道如何當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 
} 
+0

人使用_fstat()? – DinGODzilla

回答

3

我懷疑......但我不確定,Windows上的fds和套接字使用單獨的名稱空間。因此,套接字和文件的編號可能相同,當您撥打is_net_socket時,無法知道您正在談論的是哪一個。

嘗試打印出套接字和fd號碼,看看它們是否在同一時間相同。

+0

在Windows上,WinSock2(自NT4以來的標準)套接字是內核對象句柄(File對象,AFD或Tcp句柄),這就是爲什麼你可以在它們上調用標準的ReadFile和WriteFile函數的原因。內核對象的所有句柄都在同一個表中(每個進程)並且不重疊。即使它們碰巧有不同的實現和不同的值,在下一個版本中也可能會發生變化。處理值應該被視爲不透明。 –

+0

@ChrisSmith:我們在這裏討論'SOCKET',這不是我上次檢查時的'HANDLE'。 –

+0

如果你看'winsock2.h',有'typedef UINT_PTR SOCKET'這一行。 'UINT_PTR'包含一個實際的內核句柄。這就是爲什麼您可以將它與常規文件IO API一起使用的原因:否則無法正常工作。出於這個原因,SOCKET有時被稱爲「套接字句柄」。 –

3

如果Windows'C'庫有dup(),你可以嘗試重複它,這應該會失敗的套接字,但成功的文件fd。所以:

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

警告:未經檢驗的理論或未經測試的依賴;-)請注意,如果你用完了FD的的,這將返回錯誤的結果。另一個副作用是,如果它是一個文件,它將被刷新並更新其目錄條目。總而言之,它可能很糟糕。我甚至可能自己冷靜下來。

+0

+1:創造性濫用I/O系統基礎! – wallyk

+0

這很好,我真的希望它是副作用免費。沒有其他想法?這是開始:) – DinGODzilla

+0

這應該不會有副作用。只關閉打開文件的最後一個打開的文件描述符,而不是任何文件描述符,都應該有副作用。其實我認爲這個解決方案相當不錯。 –

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 
} 
+0

是的,這樣無關乎操作系統對文件的表示是什麼;你正在跟蹤它自己。 –

9

不知道你在哪裏得到的想法,Windows將不會允許您使用SOCKET手柄的文件 - 如Socket Handles頁面上明確提出:

套接字句柄可以選擇性地作爲Windows套接字2中的文件句柄。來自Winsock提供程序的套接字句柄可以與其他非Winsock函數(如ReadFile,WriteFile,ReadFileEx和WriteFileEx)一起使用。

不管怎麼說,作爲如何它們之間在Windows上區分,見函數NtQueryObject,這將返回\Device\Tcp一個暱稱,如果傳遞給它的手柄是一個開放的SOCKET。閱讀本次調用返回的結構的「備註」部分。

注意,這種方法只適用於XP和起來,將無法在Windows 2000(這我假設是足夠大,它不影響你。)

相關問題