2011-06-23 13 views
15

en UNIX todo es un archivo enfoque de la función read(), write(), close() no es compatible con Win32.Determinar entre el encaje y FD

quiero emular, pero no tienen idea de cómo distinguir cuando es socktoma o fd en 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) 
{ 
    // ...? 
} 

Esto debería funcionar como en:

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" 

Cómo implementar is_net_socket con el fin de utilizarla como en:

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

Cualquier persona _fstat utilizado()? – DinGODzilla

Respuesta

3

sospecho ... pero yo soy no estoy seguro de que fds y sockets en Windows usen espacios de nombres separados. Por lo tanto, el número para un socket y un archivo podría ser el mismo, y es imposible saber de cuál está hablando cuando llame al is_net_socket.

Intente imprimir los números de socket y fd para ver si son iguales el uno al otro al mismo tiempo.

+0

En Windows, WinSock2 (estándar desde NT4) enchufes son los identificadores de objetos (objetos del kernel archivo, ya sea AFD o maneja TCP), por lo que se puede llamar a las funciones estándar ReadFile y WriteFile en ellos. Todos los identificadores de los objetos del núcleo están en la misma tabla (por proceso) y no se superponen. Incluso si tuvieran diferentes implementaciones y valores diferentes, eso siempre podría cambiar en la próxima versión. Los valores de control deben tratarse como opacos. –

+0

@ChrisSmith: Estamos hablando de 'SOCKET' aquí, que no es un' en asa última vez que lo comprobé. –

+0

Si nos fijamos en 'winsock2.h', no es la línea' typedef UINT_PTR hembra; '. Ese 'UINT_PTR' contiene un manejador de kernel real. Es por eso que puede usarlo con las API de IO de archivos normales: de lo contrario no funcionaría. 'SOCKET's a veces se llaman" manejadores de socket "en la documentación por ese motivo. –

3

Si la biblioteca 'C' de Windows tiene dup() puede intentar duplicarla, lo que debería fallar para un socket pero tener éxito para un archivo fd. Por lo tanto:

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

Advertencia: la teoría no probada con dependencia no probado ;-) Tenga en cuenta que esto podría volver a resultados engañosos si se le acaba el FD. Otro efecto secundario es que si se trata de un archivo, se purgará y se actualizará su entrada en el directorio. En general, probablemente es una mierda francamente. Incluso podría rechazarlo yo mismo.

+0

1: abuso creativo de los fundamentos de E/S del sistema i! – wallyk

+0

Es bueno por desgracia yo realmente quiero que sea libre de efectos secundarios. No hay otras ideas? Este principio era bueno :) – DinGODzilla

+0

Esto no debería tener efectos secundarios. Solo cerrar el último descriptor de archivo abierto para un archivo abierto, no cualquier descriptor de archivo para él, debería tener efectos secundarios. En realidad, creo que esta solución es bastante buena. –

5

Supongo que puede usar seleccionar para consultar el estado de un socket.

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

recomendaría agrupación desc su archivo y tomas de corriente en una sola estructura. Puedes declarar una enumeración para decir si el descriptor es un archivo o socket. Sé que esto puede no ser tan dinámico como lo desees, pero generalmente cuando creas aplicaciones portátiles, es mejor abstraer esos detalles.

Ejemplo:

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

Sí, de esa manera no importa cuál es la representación de archivos del sistema operativo; lo estás haciendo tú mismo. –

9

No está seguro de dónde obtiene la idea de que Windows no le permitirá utilizar SOCKET mangos como archivos - como se indica claramente en la página Socket Handles:

Un manipulador de socket puede ser opcionalmente un identificador de archivo en Windows Sockets 2. Un manipulador de socket de un proveedor de Winsock se puede usar con otras funciones que no son Winsock como ReadFile, WriteFile, ReadFileEx y WriteFileEx.

De todas formas, en cuanto a la forma en distinguir entre ellos en Windows, consulte la función NtQueryObject, que devolverá un nombre de mango de \Device\Tcp si el mango se le ha pasado es un proceso abierto SOCKET.Lea la sección "Observaciones" para la estructura devuelta por esta llamada.

Tenga en cuenta que este método sólo funciona XP y arriba, y se producirá un error en Windows 2000 (que estoy suponiendo que es lo suficientemente grande que no le afecta.)

Cuestiones relacionadas