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

 

 

Feel free to comment if you can add help to this page or point out issues and solutions you have found. I do not provide support on this site, if you need help with a problem head over to stack overflow.

Comments

Your email address will not be published. Required fields are marked *