2009-08-09 15 views
6

W jaki sposób aplikacja C# może łatwo komunikować się z instancją siebie znajdującą się na innym komputerze, który znajduje się w tej samej sieci i przesyłać pliki i dane?W jaki sposób aplikacja C# może łatwo komunikować się i przesyłać pliki w sieci?

Założenie, że komputery w sieci mają ustalone lokalne adresy IP i znają się nawzajem na adresach IP. Czy byłby również sposób na komunikację, jeśli adresy IP nie są znane? na podstawie jakiegoś protokołu odkrywania?

Usłyszałem, że usługa "Bonjour" od Apple była dobrym protokołem. Czy możemy komunikować się za jego pośrednictwem z naszych aplikacji Windows? Czy musisz użyć "gniazd". Poszukuję przede wszystkim bibliotek lub przykładowego kodu, który w prosty sposób zaspokoi moje potrzeby, nie chcę tworzyć własnego protokołu opartego na protokole TCP ani nic podobnego!

Odpowiedz

2

Do przesyłania plików/danych można używać klas TcpClient/TcpListener, co jest ładną abstrakcją dla bardziej rozbudowanych funkcjonalności gniazd. Możesz też po prostu użyć aplikacji jako serwera HTTP, używając klasy HttpListener, jeśli jest to łatwiejsze/bardziej odpowiednie dla twojej aplikacji.

Do wykrywania, jeśli możesz mieć serwer centralny; wtedy każdy klient może połączyć się z serwerem podczas uruchamiania, aby się zarejestrować i pobrać listę innych klientów online i ich adresów IP. Kolejna komunikacja może następnie odbywać się bezpośrednio między klientami.

Odmianą tego schematu jest umożliwienie serwerowi centralnemu działania jako proxy, przez który przepływa cały ruch między klientami. Byłoby to głównie pomocne w przezwyciężeniu problemów z zaporą lub routingiem, jeśli klienci nie znajdują się w tej samej sieci (więc prawdopodobnie nie jest to potrzebne w twoim scenariuszu).

+0

zajęć ASP.Net? Szukałem komunikacji między aplikacjami Windows. –

+0

Co masz na myśli? Żadna z wymienionych klas nie jest klasami ASP .NET. – driis

2

Wspaniałą rzeczą plików i gniazd w C# jest to, że są one narażone zarówno jako strumienie. Kopiowanie dużego pliku z jednego strumienia do drugiego jest bardzo proste:

byte[] data = new byte[1024]; 
while(true) { 
int bytesRead = filestream.read(data,0,data.Length); 
if (bytesRead==0) break; 
netstream.write(data,0,bytesRead); 
} 

Następnie wystarczy zamknąć gniazdo, gdy skończysz.

Jeśli chcesz wysłać metadane (nazwy plików, rozmiary) lub nie chcesz zamykać połączenia, potrzebujesz jakiegoś protokołu do obsługi tego. FTP używa dwóch oddzielnych gniazd (jeden dla metadanych, drugi dla danych, to się nazywa komunikacją poza pasmem). Jeśli korzystasz z sieci LAN bez zapór ogniowych, możesz to całkowicie zaakceptować. Z drugiej strony, jeśli chcesz wykonać transfer internetowy, otwarcie jednego portu jest zadaniem trudnym, a dwa nie do zniesienia. Jeśli nie przejmujesz się zbytnio wydajnością, możesz zakodować bajty w kodowaniu base64, co zapewni, że mieszczą się w pewnym zakresie bajtów. Dzięki base64 możesz rozdzielać wiadomości za pomocą znaków nowej linii lub innych znaków niealfanumerycznych. Następnie w pierwszej wiadomości wpisz nazwę pliku, rozmiar lub cokolwiek innego, następnie wyślij dane jako drugą wiadomość, a następnie wyślij wiadomość "to jest cały plik", aby klient wiedział, że to zrobione.

Inną taktyką dla wiadomości jest użycie sekwencji ucieczki. Na przykład, weź swój bytestream i zamień każde wystąpienie "\ 0" na "\ 0 \ 0". Teraz użyj "\ 0 \ 1", aby zasygnalizować koniec wiadomości, który nie jest gwarantowany w wiadomości danych. Odkoduj "\ 0 \ 0" z powrotem do "\ 0" na końcu odbiorczym.Działa to wystarczająco dobrze w C, ale uważam, że w praktyce pętla przez każdy bajt może być wolniejsza niż czytanie całych buforów w C#.

Najlepszym sposobem jest przyjęcie pewnego rodzaju protokołu o długości adaptacyjnej. Na przykład wyślij dane w porcjach o określonym rozmiarze (powiedzmy 512 bajtów). Przed każdym kawałkiem wyślij 32-bitowe int reprezentujące rozmiar porcji przez System.BitConverter. Więc wiadomości wyglądać następująco (po angielsku):

Here's 512 bytes: 
[data] 
Here's 512 bytes: 
[data] 
Here's 32 bytes: 
[data] 
Here's 4 bytes: 
That was the whole file 

Zaletą jest to, że można zrobić kopii/odczytu bufory pracować dla Ciebie (czytanie 512 bajtów na raz), co oznacza, swoją przepustowość jest ograniczona przez stos sieciowy zamiast twojego kodu C#. Klient odczytuje 32-bitową int o stałej długości, która informuje go o rozmiarze bufora, który powinien wykorzystać w następnym segmencie [data].

Oto niektóre kodu pisać wiadomości tak:

 logger.logger.debug("Sending message of length " + length); 
     byte[] clength = System.BitConverter.GetBytes(buffer.Length); 
     plaintextStream.Write(clength,0,clength.Length); 
     plaintextStream.Write(buffer,0,buffer.Length); 
     plaintextStream.Flush(); 

A oto niektóre kod, aby je odczytać:

   byte[] intbuf = new byte[int_32_size]; 
     int offset = 0; 
     while (offset < int_32_size) 
     { 
      int read = 0; 

      read = d.plaintextStream.Read(intbuf,offset,int_32_size - offset); 
      offset += read; 

     } 
     int msg_size = System.BitConverter.ToInt32(intbuf,0); 
     //allocate a new buffer to fill the message 
     byte[] msg_buffer = new byte[msg_size]; 
     offset = 0; 
     while (offset < msg_size) 
     { 
      int read = 0; 

      read = d.plaintextStream.Read(msg_buffer,offset,msg_size - offset); 
      offset += read; 
     } 


     return msg_buffer; 
Powiązane problemy