send_file() — Send file data over a socket

Standards

Standards / Extensions C or C++ Dependencies
z/OS® UNIX both  

Format

#define _OPEN_SYS_SOCK_EXT2
#include <sys/socket.h>

int send_file(int *socket_ptr, struct sf_parms *sf_struct, int options);

General description

The send_file() function sends data from the file associated with the open file handle over the connection associated with the socket.

The function takes the following arguments:

socket_ptr
A pointer to a socket file descriptor.
sf_struct
A pointer to a structure that contains variables needed by sendfile - header information, file information, trailer information and results of operation. See below for details.
options
Specifies one of the following options:
SF_CLOSE
Close the connection after the data has been successfully sent or queued for transmission.
SF_REUSE
Prepare the socket for reuse after the data has been successfully sent or queued for transmission and the existing connection closed.

Send_File Structure - sf_parms

Argument sf_struct points to a struct sf_parms that contains the file descriptor, a header data buffer, and a trailer data buffer.

The struct sf_parms is defined in <sys/sockets.h> and contains the following elements:
header_data
Pointer to a buffer that contains header data which is to be sent before the file data. It may be a NULL pointer if header_length is zero.
header_length
Specifies the number of bytes in the header_data. It must be set to zero to indicate that header data is not to be sent.
file_descriptor
File descriptor for a file that has been opened for read. This is the descriptor for the file that contains the data to be transmitted.
file_size
The size, in bytes, of the file associated with file_descriptor. This field is filled in by the system.
file_offset
Specifies the byte offset into the file from which to start sending data.
file_bytes
Specifies the number of bytes from the file to be transmitted. Setting file_bytes to -1 will transmit the entire file from the offset. In this case the system will replace the -1 with (actual file size - file_offset). Setting file_bytes to 0 will result in no file data being transmitted and file_descriptor is ignored. If file_descriptor is not a regular file it may be necessary to supply a specific value for file_bytes unless a normal End Of File (EOF) indication is expected from file_descriptor during this operation or you simply want the operation to run forever transferring bytes as they arrive.
trailer_data
Pointer to a buffer that contains trailer data which is to be sent after the file data.
trailer_length
Specifies the number of bytes in the trailer_data.
bytes_sent
Number of bytes that were sent in this call to send_file(). If it takes multiple calls to send_file() to send all the data (due to signal-handling) then this field contains the value for the last call to send_file(), it is not a running total. This field is set by the system.

The send_file() function attempts to write header_length bytes from the buffer pointed to by header_data, followed by file_bytes from the file associated with file_descriptor, followed by trailer_length bytes from the buffer pointed to by trailer_data, over the connection associated with the socket pointed to by socket_ptr.

As data is sent, the system will update elements in sf_struct so that if the send_file() function is interrupted by a signal, the application simply needs to reissue send_file()

If the application sets file_offset > the actual file size, or file_bytes > (the actual file size - file_offset), the return value will be -1 and errno set to EINVAL.

If O_NONBLOCK is set on the socket file descriptor, the function may return -1 with errno set to EWOULDBLOCK or EAGAIN, or it may complete before all the data is sent. If O_NONBLOCK is not set, send_file() blocks until the requested data can be sent.

SF_CLOSE and SF_REUSE will only be effective after all the data has been sent successfully.

If options = SF_REUSE, and socket reuse is not supported, the system will close the socket and set the socket pointed to by socket_ptr to -1. See Application usage for details.

Application usage

send_file() is designed to work with accept_and_recv() to provide an efficient file transfer capability for a connection oriented server with short connection times and high connection rates.

On the first call to accept_and_recv(), it is recommended that the application set the socket pointed to by accept_socket to -1. This will cause the system to assign the accepting socket. On the call to send_file(), if the application requests socket reuse (options = SF_REUSE) and the system does not support it, the system will close the socket pointed to by socket_ptr and will set the socket pointed to by socket_ptr to -1. The application then passes this value onto the next call to accept_and_recv() (by setting accept_socket = *socket_ptr).

To take full advantage of the performance improvements offered by the accept_and_recv() and send_file() functions, a process/thread model different from the one where a parent accepts in a loop and spins off child process threads is needed. The parent/process thread is eliminated. Multiple worker processes/threads are created, and each worker process/thread then executes the accept_and_recv() and send_file() functions in a loop. The performance benefits of accept_and_recv() and send_file() include fewer buffer copies, recycled sockets, and optimal scheduling.

Returned value

If successful, send_file() returns 0.

send_file() returns 1 if the request was interrupted by a signal, or because a nonblocking descriptor would have blocked, while sending data. Since the sf_parms structure is updated by the system to account for the data that has been sent you can continue the operation from where is was interrupted by recalling send_file() without changing the sf_parms structure.

If unsuccessful, send_file() returns -1 and sets errno to one of the following values:

Error Code
Description
EACCES
The calling process does not have the appropriate privileges.
EAGAIN
socket_ptr is in nonblocking mode and no data buffers are available or the SO_SNDTIMEO timeout value was reached before buffers became available.
EBADF
One of the following occurred:
  1. socket_ptr is not a valid descriptor or was not open for writing.
  2. file_descriptor is not a valid descriptor or was not open for reading.
ECONNABORTED
A connection has been aborted.
ECONNRESET
A connection has been forcibly closed by a peer.
EFAULT
The data buffer pointed to by socket_ptr, file_size, header_data, or trailer_data was not valid.
EINTR
send_file() was interrupted by a signal that was caught before any data was sent.
EINVAL
The value specified by options is not valid.
EIO
An I/O error occurred.
EMSGSIZE
The message is too large to be sent all at once, as the socket requires.
ENETDOWN
The local interface to reach the destination is unknown.
ENETUNREACH
No route to the destination is present.
ENOBUFS
No buffer space is available.
ENOMEM
There was insufficient memory available to complete the operation.
ENOSR
There were insufficient STREAMS resources available for the operation to complete.
ENOSYS
This function is not supported in the current environment.
ENOTCONN
The socket is not connected.
ENOTSOCK
The file descriptor pointed to by the socket_ptr argument does not refer to a socket.
EPIPE
The socket is shutdown for writing, or the socket is in connection mode and is no longer connected.
EWOULDBLOCK
socket_ptr is in nonblocking mode and no data buffers are available or the SO_SNDTIMEO timeout value was reached before buffers became available.

Related information