Déterminer entre socket et fd

Sur unix tout est une approche de fichier de function read() , write() , close() n’est pas supporté sous Win32.

Je veux l’imiter, mais je n’ai aucune idée de la façon de distinguer quand sock est socket ou fd sur WinSocks2.

 //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) { // ...? } 

Cela devrait fonctionner comme dans:

 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" 

Comment implémenter is_net_socket pour l’utiliser comme dans:

 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 } 

Vous ne savez pas exactement où vous pensez que Windows ne vous autorisera pas à utiliser les SOCKET comme des fichiers – comme cela est clairement indiqué sur la page Socket Handles :

Un handle de socket peut éventuellement être un handle de fichier dans Windows Sockets 2. Un handle de socket provenant d’un fournisseur Winsock peut être utilisé avec d’autres fonctions non-Winsock telles que ReadFile, WriteFile, ReadFileEx et WriteFileEx.

Quoi qu’il en soit, pour savoir comment les distinguer sous Windows, voir la fonction NtQueryObject , qui renverra un nom de \Device\Tcp de \Device\Tcp si le \Device\Tcp qui lui est transmis est un SOCKET ouvert. Lisez la section “Remarques” pour la structure renvoyée par cet appel.

Notez que cette approche ne fonctionne que sous XP et ne fonctionnera pas sous Windows 2000 (ce qui est assez vieux pour que cela ne vous concerne pas).

Je suppose que vous pouvez utiliser select pour interroger le statut d’un socket.

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

Je vous recommande de regrouper votre fichier desc et sockets dans une seule structure. Vous pouvez déclarer une énumération pour savoir si le descripteur est un fichier ou une socket. Je sais que cela peut ne pas être aussi dynamic que vous le souhaitez, mais généralement, lorsque vous créez des applications portables, il est préférable de les supprimer.

Exemple:

 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 } 

Je soupçonne … mais je ne suis pas sûr que fds et sockets sur Windows utilisent des espaces de noms séparés. Par conséquent, le numéro d’un socket et d’un fichier pourrait être le même, et il est impossible de savoir lequel vous parlez lorsque vous appelez is_net_socket .

Essayez d’imprimer les numéros de socket et de fd pour voir s’ils sont identiques en même temps.

Si la bibliothèque Windows ‘C’ a dup (), vous pouvez essayer de la piéger, ce qui devrait échouer pour un socket mais réussir pour un fichier fd. Alors:

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

Attention: théorie non testée avec une dépendance non testée 😉 Notez que cela renverrait des résultats trompeurs si vous êtes à court de fd. Un autre effet secondaire est que si c’est un fichier, il sera vidé et son entrée de répertoire mise à jour. Dans l’ensemble, c’est probablement nul. Je pourrais même le réduire moi-même.