2011-06-23 13 views
15

na Unix wszystko jest plikiem podejście funkcji read(), write(), close() nie jest obsługiwany na Win32.Ustal między gniazdem a fd

chcę go naśladować, ale nie mają pojęcia jak odróżnić kiedy sock jest gniazdo lub fd na 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) 
{ 
    // ...? 
} 

To powinno działać jak w:

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" 

Jak wdrożyć is_net_socket w celu wykorzystania go jako w:

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

Każdy używany _fstat()? – DinGODzilla

Odpowiedz

3

podejrzewam ... ale jestem nie wiesz, że fds i gniazda w systemie Windows używają oddzielnych przestrzeni nazw. Dlatego numer gniazda i pliku może być taki sam i nie można dowiedzieć się, o którym mówisz, gdy dzwonisz pod numer is_net_socket.

Spróbuj wydrukować numery gniazd i fd, aby sprawdzić, czy są one takie same jak inne w tym samym czasie.

+0

W systemie Windows gniazda WinSock2 (standardowe od NT4) są uchwytami obiektów jądra (obiekty File, albo uchwyty AFD lub Tcp), dlatego można wywoływać na nich standardowe funkcje ReadFile i WriteFile. Wszystkie uchwyty do obiektów jądra znajdują się w tej samej tabeli (na proces) i nie nakładają się. Nawet jeśli miały różne implementacje i różne wartości, które zawsze mogły się zmienić w następnej wersji. Wartości uchwytów należy traktować jako nieprzezroczyste. –

+0

@ChrisSmith: Mówimy tutaj o "SOCKET", który nie jest "UTRZYMANIEM" ostatnio, kiedy sprawdzałem. –

+0

Jeśli spojrzysz w 'winsock2.h', pojawi się wiersz' typedef UINT_PTR SOCKET; '. To 'UINT_PTR' zawiera rzeczywisty uchwyt jądra. Z tego powodu można go używać w zwykłych plikach API IO: nie działa inaczej. 'GNIAZDKI' są czasami nazywane "uchwytami gniazdowymi" w dokumentacji z tego powodu. –

3

Jeśli biblioteka "C" systemu Windows ma dup(), możesz spróbować ją zduplikować, co powinno zakończyć się niepowodzeniem dla gniazda, ale powiodło się dla pliku fd. Więc:

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

Ostrzeżenie: niesprawdzona teoria z niesprawdzonych uzależnienia ;-) Zauważ, że to powrót błędne wyniki, jeśli zabraknie FD. Innym skutkiem ubocznym jest to, że jeśli jest to plik, zostanie przepłukany, a jego pozycja w katalogu zostanie zaktualizowana. Podsumowując, prawdopodobnie to jest do bani. Mogę nawet powiedzieć to samo.

+0

+1: Twórcze nadużywanie podstaw systemu i/o! – wallyk

+0

To jest naprawdę dobre, naprawdę chcę, żeby był wolny od efektów ubocznych. Nie ma innych pomysłów? To był dobry początek :) – DinGODzilla

+0

To nie powinno mieć efektów ubocznych. Tylko zamykanie ostatniego otwartego deskryptora pliku dla otwartego pliku, a nie jakiegokolwiek deskryptora pliku, powinno mieć efekty uboczne. Uważam, że to rozwiązanie jest raczej dobre. –

5

Przypuszczam, że możesz użyć opcji, aby zapytać o stan gniazda.

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

Polecam grupowania swoją desc plików i gniazd w jednej struktury. Możesz zadeklarować wyliczenie, aby stwierdzić, czy deskryptor jest plikiem lub gniazdem. Wiem, że to może nie być tak dynamiczne, jak chcesz, ale generalnie, gdy tworzysz aplikacje przenośne, najlepiej je usuwać.

Przykład:

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

Tak, w ten sposób nie ma znaczenia, jaka jest reprezentacja plików OS; sam to monitorujesz. –

9

Nie wiesz, gdzie jesteś coraz pomysł, że system Windows nie pozwoli Ci korzystać SOCKET uchwyty jak pliki - jak jasno określonych na stronie Socket Handles:

Uchwyt gniazda może opcjonalnie być uchwytem pliku w gniazdach systemu Windows 2. Uchwyt gniazda od dostawcy Winsock może być używany z innymi funkcjami innymi niż Winsock, takimi jak ReadFile, WriteFile, ReadFileEx i WriteFileEx.

Tak czy inaczej, jak do jak ich odróżnić w systemie Windows, zobacz funkcję NtQueryObject, która będzie zwracać nazwę uchwytu z \Device\Tcp jeśli uchwyt przeszedł do niej jest otwarty SOCKET.Przeczytaj sekcję "Uwagi" dla struktury zwróconej przez to połączenie.

Należy zauważyć, że takie podejście działa tylko XP i do góry, a nie w systemie Windows 2000 (który ja zakładając jest na tyle stary, że nie ma wpływu na ciebie.)