La cosa grandiosa di file e le prese in C# è che sono entrambi esposti come flussi. Copiare un file di grandi dimensioni da uno stream a un altro è piuttosto semplice:
byte[] data = new byte[1024];
while(true) {
int bytesRead = filestream.read(data,0,data.Length);
if (bytesRead==0) break;
netstream.write(data,0,bytesRead);
}
Quindi basta chiudere lo zoccolo quando hai finito.
Se si desidera inviare metadati (nomi di file, dimensioni) o non si desidera chiudere la connessione, è necessario un qualche tipo di protocollo per gestirlo. FTP utilizza due socket separati (uno per i metadati, uno per i dati, chiamato comunicazione out-of-band). Se sei su una LAN senza firewall, ciò può essere perfettamente accettabile. D'altra parte, se si desidera effettuare il trasferimento su Internet, ottenere una singola porta aperta è un'attività abbastanza difficile, e due sono insopportabili. Se non ti preoccupi troppo delle prestazioni, potresti codificare i byte nella codifica base64, il che assicura che siano all'interno di un certo intervallo di byte. Con base64, puoi separare i messaggi con newline o altri caratteri non alfanumerici. Quindi nel primo messaggio includi il nome file, la dimensione o qualsiasi altra cosa, quindi invia i dati come un secondo messaggio, quindi invia un messaggio "questo è l'intero file" in modo che il client sappia che è fatto.
Un'altra tattica per i messaggi è l'utilizzo di una sequenza di escape. Per esempio, prendi il tuo puntatore e sostituisci ogni istanza di '\ 0' con '\ 0 \ 0'. Ora usa '\ 0 \ 1' per segnalare la fine del messaggio, che è garantito non essere contenuto nel tuo messaggio di dati. Decodificare '\ 0 \ 0' su '\ 0' sul lato ricevente.Funziona abbastanza bene in C, ma trovo che, in pratica, il looping di ogni byte può essere più lento della lettura di interi buffer in C#.
Il modo migliore è adottare una sorta di protocollo di lunghezza adattiva. Ad esempio, invia i dati in blocchi di una certa dimensione (ad esempio 512 byte). Prima di ogni blocco, invia un int a 32 bit che rappresenta la dimensione del blocco tramite System.BitConverter. Così i messaggi appaiono così (inglese):
Here's 512 bytes:
[data]
Here's 512 bytes:
[data]
Here's 32 bytes:
[data]
Here's 4 bytes:
That was the whole file
Il vantaggio è che si può fare la copia/lettura buffer di lavoro per voi (la lettura di 512 byte alla volta), il che significa la velocità effettiva è limitata dal tuo stack di rete invece del tuo codice C#. Il client legge l'int a 32 bit a lunghezza fissa che gli consente di conoscere la dimensione del buffer che dovrebbe utilizzare per il prossimo segmento [dati].
Ecco il codice per scrivere i messaggi del genere:
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();
Ed ecco un po 'di codice per leggere loro:
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;
Classi ASP.Net? Stavo cercando una comunicazione tra le app di Windows. –
Cosa intendi? Nessuna delle classi che menziono sono classi ASP .NET. – driis