GNU/Linux >> Tutoriales Linux >  >> Linux

Enviar y recibir un archivo en programación de socket en Linux con C/C++ (GCC/G++)

Haz un man 2 sendfile . Solo necesita abrir el archivo de origen en el cliente y el archivo de destino en el servidor, luego llamar a sendfile y el kernel cortará y moverá los datos.


La solución más portátil es simplemente leer el archivo en fragmentos y luego escribir los datos en el socket, en un bucle (y al revés al recibir el archivo). Asignas un búfer, read en ese búfer, y write de ese búfer a tu socket (también puedes usar send y recv , que son formas específicas de socket de escribir y leer datos). El esquema se vería así:

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

Asegúrate de leer la documentación de read y write cuidadosamente, especialmente al manejar errores. Algunos de los códigos de error significan que debe volver a intentarlo, por ejemplo, repetir el bucle de nuevo con un continue declaración, mientras que otros significan que algo está roto y debe parar.

Para enviar el archivo a un socket, hay una llamada al sistema, sendfile que hace justo lo que quieres. Le dice al kernel que envíe un archivo de un descriptor de archivo a otro, y luego el kernel puede encargarse del resto. Hay una advertencia de que el descriptor del archivo fuente debe ser compatible con mmap (como en, ser un archivo real, no un socket), y el destino debe ser un socket (por lo que no puede usarlo para copiar archivos o enviar datos directamente de un socket a otro); está diseñado para admitir el uso que describe, de enviar un archivo a un socket. Sin embargo, no ayuda a recibir el archivo; tendrías que hacer el bucle tú mismo para eso. No puedo decirte por qué hay un sendfile llamada pero no análoga recvfile .

Cuidado con que sendfile es específico de Linux; no es portable a otros sistemas. Otros sistemas suelen tener su propia versión de sendfile , pero la interfaz exacta puede variar (FreeBSD, Mac OS X, Solaris).

En Linux 2.6.17, el splice Se introdujo una llamada al sistema y, a partir de la versión 2.6.23, se usa internamente para implementar sendfile . splice es una API de propósito más general que sendfile . Para una buena descripción de splice y tee , vea la explicación bastante buena del propio Linus. Señala cómo usar splice es básicamente como el ciclo anterior, usando read y write , excepto que el búfer está en el kernel, por lo que los datos no tienen que transferirse entre el kernel y el espacio del usuario, o es posible que nunca pasen a través de la CPU (lo que se conoce como "E/S de copia cero").


Linux
  1. Encuentra archivos y directorios en Linux con el comando de búsqueda

  2. Copie y pegue en la línea de comandos de Linux con xclip

  3. Escenarios en tiempo real de Linux y problemas con sus soluciones

  4. Trabajar con entrada, salida y redirección de errores en Linux

  5. Permisos de archivo en Linux con ejemplo

Descargar archivos con Wget en Linux Shell - Explicación y ejemplos

Comando WC de Linux con ejemplos

Explicación de Soft Link y Hard Link en Linux con ejemplos

Cómo trabajar con enlaces duros y suaves en Linux

Comando mailx en linux:enviar y recibir correo de Internet

Permisos y propiedad de archivos de Linux explicados con ejemplos