c - recvmsg linux receive wrong data -


i using recvmsg , sendmsg send data on asynchronous stream socket . amount of data transfer rather big, between 15 mb , 30 mb.

i cannot understand why data arrives corrupted. sending messages , reciving function gets interrupted errno eintr adn eagain.

the functions ma using :

int receive_result_with_extra(int fd, struct syscall_result * result, int extra_size, char * buf) {      struct iovec io[2];     struct msghdr msg;      int transfered=0, temp=0;      const int total =  size_result + extra_size;       clean_msg(&msg);     memset(io, 0, sizeof(io));       // result header      io[1].iov_len=size_result;      io[1].iov_base=result;     // result buffer     io[0].iov_len = extra_size;      io[0].iov_base = buf;      // iov struct      msg.msg_iov=io;     msg.msg_iovlen=2;      {        temp = recvmsg(fd,&msg, 0);              if ( temp < 0 && (errno==eagain || errno == eintr || errno == ewouldblock))          continue;        else if ( temp < 0 )           die("error receiveing data recvmsg (receive_result_with_extra)");        transfered += temp;      } while(transfered < total);       if ( transfered < 0)          die("recvmsg (receive_result_with_extra)");       assert(transfered == total);     return transfered;  } int send_result_with_extra(int fd, struct syscall_result * result, int extra_size, char * buf) {      struct iovec io[2];     struct msghdr msg;      int transfered=0, temp=0;      const int total =  size_result + extra_size;       clean_msg(&msg);     memset(io, 0, sizeof(io));       // result header      io[1].iov_len=size_result;      io[1].iov_base=result;     // result buffer     io[0].iov_len = extra_size;      io[0].iov_base = buf;      // iov struct      msg.msg_iov=io;     msg.msg_iovlen=2;      {       temp=sendmsg(fd,&msg, 0);        if ( temp < 0 && (errno == eintr || errno == eagain || errno == ewouldblock))           continue;        else if ( temp < 0)           die("failed sending data ( send_result_with_extra)");         transfered += temp;      } while( transfered < total);      if ( transfered < 0)          die("recvmsg (fstat handler)");       assert(transfered == total);      return transfered;  } 

you don't update iovecs in send/recv loops, repeatedly send same prefix / recv beginning of data buffer if data large transfer in single network packet.

i use common function both send , receive update iovec:

/**  * shrinks iovec associated msg given number of bytes.  *  * @msg    message iovec needs updating.  * @bytes  number of bytes remove beginning of iovec.  *  * @return returns 0 iff updated iovec 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 use return value of update function in condition of send/recv loops. e.g.:

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

Comments

Popular posts from this blog

How to mention the localhost in android -

php - Calling a template part from a post -