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;
zajęć ASP.Net? Szukałem komunikacji między aplikacjami Windows. –
Co masz na myśli? Żadna z wymienionych klas nie jest klasami ASP .NET. – driis