You don't update the iovecs in your send/recv loops, so you will repeatedly send the same prefix / recv into the beginning of the data buffer if the data is too large to transfer in a single network packet.
I would use a common function for both send and receive to update the iovec
:
/**
* Shrinks the iovec associated with a msg by a given number of bytes.
*
* @msg The message whose iovec needs updating.
* @bytes Number of bytes to remove from the beginning of the iovec.
*
* @return Returns 0 iff the updated iovec is empty.
*/
int update_buffer(struct msghdr* msg, size_t bytes) {
while (msg->msg_iovlen > 0) {
if (bytes < msg->msg_iov[0].iov_len) {
msg->msg_iov[0].iov_len -= bytes;
msg->msg_iov[0].iov_base += bytes;
return 1;
}
bytes -= msg->msg_iov[0].iov_len;
++msg->msg_iov;
--msg->msg_iovlen;
}
return 0;
}
You can then use the return value of this update function in the condition of your send/recv loops. E.g.:
do {
do {
temp = sendmsg(fd, &msg, 0);
} while (temp < 0 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
if (temp < 0)
die("Failed sending data (send_result_with_extra)");
} while (update_buffer(&msg, temp));