GNU/Linux >> Linux Esercitazione >  >> Linux

Invia e ricevi un file nella programmazione socket in Linux con C/C++ (GCC/G++)

Fai un man 2 sendfile . Devi solo aprire il file di origine sul client e il file di destinazione sul server, quindi chiamare sendfile e il kernel taglierà e sposterà i dati.


La soluzione più portatile è solo leggere il file in blocchi, quindi scrivere i dati nel socket, in un ciclo (e allo stesso modo, viceversa quando si riceve il file). Allochi un buffer, read in quel buffer e write da quel buffer nel tuo socket (puoi anche usare send e recv , che sono modi specifici del socket di scrivere e leggere i dati). Lo schema sarebbe simile a questo:

while (1) {
    // Read data into buffer.  We may not have enough to fill up buffer, so we
    // store how many bytes were actually read in bytes_read.
    int bytes_read = read(input_file, buffer, sizeof(buffer));
    if (bytes_read == 0) // We're done reading from the file
        break;
    
    if (bytes_read < 0) {
        // handle errors
    }
    
    // You need a loop for the write, because not all of the data may be written
    // in one call; write will return how many bytes were written. p keeps
    // track of where in the buffer we are, while we decrement bytes_read
    // to keep track of how many bytes are left to write.
    void *p = buffer;
    while (bytes_read > 0) {
        int bytes_written = write(output_socket, p, bytes_read);
        if (bytes_written <= 0) {
            // handle errors
        }
        bytes_read -= bytes_written;
        p += bytes_written;
    }
}

Assicurati di leggere la documentazione per read e write con attenzione, soprattutto quando si gestiscono gli errori. Alcuni dei codici di errore indicano che dovresti semplicemente riprovare, ad esempio semplicemente ripetere il ciclo con un continue dichiarazione, mentre altri significano che qualcosa è rotto e devi fermarti.

Per inviare il file a un socket, c'è una chiamata di sistema, sendfile che fa proprio quello che vuoi. Dice al kernel di inviare un file da un descrittore di file a un altro, e quindi il kernel può occuparsi del resto. C'è un avvertimento che il descrittore del file sorgente deve supportare mmap (come in, essere un file effettivo, non un socket) e la destinazione deve essere un socket (quindi non puoi usarlo per copiare file o inviare dati direttamente da un socket a un altro); è progettato per supportare l'uso che descrivi, di inviare un file a un socket. Tuttavia, non aiuta a ricevere il file; dovresti fare tu stesso il ciclo per quello. Non posso dirti perché c'è un sendfile call ma nessun analogo recvfile .

Attenzione a quel sendfile è specifico per Linux; non è portabile su altri sistemi. Altri sistemi hanno spesso la propria versione di sendfile , ma l'interfaccia esatta può variare (FreeBSD, Mac OS X, Solaris).

In Linux 2.6.17, il splice è stata introdotta la chiamata di sistema e dalla 2.6.23 è utilizzata internamente per implementare sendfile . splice è un'API più generica rispetto a sendfile . Per una buona descrizione di splice e tee , vedi la spiegazione piuttosto buona dello stesso Linus. Sottolinea come utilizzare splice è fondamentalmente proprio come il ciclo sopra, usando read e write , tranne per il fatto che il buffer si trova nel kernel, quindi i dati non devono essere trasferiti tra il kernel e lo spazio utente, o potrebbero anche non passare mai attraverso la CPU (noto come "I/O a copia zero").


Linux
  1. Trova file e directory su Linux con il comando find

  2. Copia e incolla nella riga di comando di Linux con xclip

  3. Linux Real Time Scenari e problemi con le loro soluzioni

  4. Permessi dei file in Linux con esempio

  5. C++ nuovo operatore thread safety in linux e gcc 4

Scarica file con Wget sulla shell Linux - Spiegazione ed esempi

Comando Linux WC con esempi

Spiegazione di Soft Link e Hard Link in Linux con esempi

Come lavorare con hardlink e softlink in Linux

comando mailx in linux – invia e ricevi posta Internet

Permessi e proprietà dei file Linux spiegati con esempi