gpt4 book ai didi

c - recvmsg linux 接收到错误的数据

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:56:22 34 4
gpt4 key购买 nike

我正在使用 recvmsg 和 sendmsg 通过异步 STREAM 套接字发送数据。要传输的数据量相当大,在 15 MB 到 30 MB 之间。

我不明白为什么数据到达时损坏了。发送消息和接收函数被 errno EINTR 和 EAGAIN 中断。

我使用的功能是:

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;

do {
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;

do {
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;
}

最佳答案

您不会在发送/接收循环中更新 iovecs,因此如果数据太大而无法在单个网络数据包中传输,您将重复发送相同的前缀/接收到数据缓冲区的开头。

我会为发送和接收使用通用函数来更新 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;
}

然后您可以在发送/接收循环的条件下使用此更新函数的返回值。例如:

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

关于c - recvmsg linux 接收到错误的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17731166/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com