If you don't have your socket set to non blocking (which means you have to deal with recv() wanting to block when you call it) then using the send() transmitfunction is no problem as it will block until the packet you are sending has gone out. However if you have O_NONBLOCK non blocking turned on so you can poll using recv() then you have a problem when sending say a large file. The send function will return the number of bytes it managed to send and you can use this to retry sending the remaining bytes, adding a delay to let the system catch up, but in our tests even adding in a 1000mS delay when this occurred we'd still get the send() function ultimately returning a -1 error before all of the data had been sent. One fix to this may be to use a different function to wait for the socket to become free again but an easier fix is just to temporarily turn blocking mode back on when you do the transmit.
Turn socket blocking mode on and off
//Set blocking to on
const int flags = fcntl(tcp_server_client_socket, F_GETFL, 0);
fcntl(tcp_server_client_socket, F_SETFL, (flags & ~O_NONBLOCK));
//Turn off blocking again
const int flags2 = fcntl(tcp_server_client_socket, F_GETFL, 0);
fcntl(tcp_server_client_socket, F_SETFL, (flags2 | O_NONBLOCK));
An example with a complete transmit handler
file_next_byte = 0;
file1 = fopen(filename_lea.c_str(), "rb");
if (file1)
{
while (file_next_byte < (filesize - 4)) //-2 checksum bytes that are already included in filesize
{
//How many bytes to send in the next block?
if (((filesize - 4) - file_next_byte) > 1024)
bytes_to_read = 1024;
else
bytes_to_read = ((filesize - 4) - file_next_byte);
file_next_byte += bytes_to_read;
//Read the bytes to a local buffer
fread(&file_data[0], sizeof(unsigned char), bytes_to_read, file1);
//Add the bytes to the checksum
for (count = 0; count < bytes_to_read; count++)
checksum += file_data[count];
//Send the bytes
//Set blocking to on
const int flags = fcntl(tcp_server_client_socket, F_GETFL, 0);
fcntl(tcp_server_client_socket, F_SETFL, (flags & ~O_NONBLOCK));
bytes_sent_count = 0;
while (bytes_sent_count < bytes_to_read) //Keep trying until it is sent
{
bytes_sent = send(tcp_server_client_socket, (char*)&file_data[bytes_sent_count], (bytes_to_read - bytes_sent_count), 0);
if (bytes_sent < bytes_to_read)
{
//delayMicroseconds(1000); //If blocking wasn't turned on then this will happen for large files and in tests using a delay isn't enough to stop a -1 error to ultimately get returned.
//With blocking turned on we don't get here in practice
}
if (bytes_sent < 0) // -1 = error
break;
bytes_sent_count += bytes_sent;
}
}
fclose(file1);
file1 = NULL;
//Turn off blocking again
const int flags2 = fcntl(tcp_server_client_socket, F_GETFL, 0);
fcntl(tcp_server_client_socket, F_SETFL, (flags2 | O_NONBLOCK));