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.
- 0
- Do not close the socket (use zero for no options).
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.
- 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
The function 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:
- socket_ptr is not a valid descriptor or was not open for writing.
- 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.