GNU/Linux >> Znalost Linux >  >> Linux

Odeslání a příjem souboru v programování soketu v Linuxu s C/C++ (GCC/G++)

Proveďte man 2 sendfile . Stačí otevřít zdrojový soubor na klientovi a cílový soubor na serveru, pak zavolat sendfile a jádro data rozseká a přesune.


Nejpřenosnějším řešením je pouze číst soubor po částech a poté zapisovat data do soketu ve smyčce (a podobně i obráceně při příjmu souboru). Vy přidělujete vyrovnávací paměť, read do této vyrovnávací paměti a write z tohoto bufferu do vašeho soketu (můžete také použít send a recv , což jsou způsoby zápisu a čtení dat specifické pro socket). Obrys by vypadal asi takto:

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;
    }
}

Nezapomeňte si přečíst dokumentaci pro read a write opatrně, zvláště při manipulaci s chybami. Některé z chybových kódů znamenají, že byste to měli zkusit znovu, například opakovat opakování s continue prohlášení, zatímco ostatní znamenají, že je něco nefunkční a musíte s tím přestat.

Pro odeslání souboru do soketu existuje systémové volání sendfile to dělá přesně to, co chcete. Říká jádru, aby poslalo soubor z jednoho deskriptoru souboru do druhého, a pak se jádro může postarat o zbytek. Existuje upozornění, že deskriptor zdrojového souboru musí podporovat mmap (stejně jako v případě, být skutečným souborem, nikoli soketem) a cílem musí být soket (nemůžete jej tedy použít ke kopírování souborů nebo odesílání dat přímo z jednoho soketu do druhého); je navržen tak, aby podporoval použití, které popisujete, odesílání souboru do soketu. Nepomůže to však s přijetím souboru; na to budete muset udělat smyčku sami. Nemohu vám říci, proč existuje sendfile volání, ale žádné analogové recvfile .

Pozor, sendfile je specifický pro Linux; není přenosný na jiné systémy. Jiné systémy mají často vlastní verzi sendfile , ale přesné rozhraní se může lišit (FreeBSD, Mac OS X, Solaris).

V Linuxu 2.6.17 splice bylo zavedeno systémové volání a od 2.6.23 se používá interně k implementaci sendfile . splice je API pro obecnější účely než sendfile . Pro dobrý popis splice a tee , viz docela dobré vysvětlení od samotného Linuse. Poukazuje na to, jak používat splice je v podstatě stejný jako smyčka výše s použitím read a write , kromě toho, že vyrovnávací paměť je v jádře, takže data se nemusí přenášet mezi jádrem a uživatelským prostorem, nebo dokonce nikdy nemusí projít CPU (známé jako "nulové kopie I/O").


Linux
  1. Najděte soubory a adresáře v Linuxu pomocí příkazu find

  2. Linuxové scénáře v reálném čase a problémy s jejich řešeními

  3. Oprávnění souborů v Linuxu s příkladem

  1. Jak odeslat e-mail s přílohou a tělem z Linuxu

  2. Bezpečnost nového operátorského vlákna v C++ v linuxu a gcc 4

  3. C/C++ s GCC:Statické přidávání zdrojových souborů do spustitelného souboru/knihovny

  1. Zkopírujte a vložte na příkazový řádek Linuxu pomocí xclip

  2. Práce s Input Output a přesměrováním chyb v Linuxu

  3. (C/C++) Jak vygenerovat spustitelný soubor, který lze spustit na Windows i Linuxu?