现在我使用SCM_RIGHTS协议发送fd (文件描述)。但有时我的fd会因为某种原因得到-1。我想告诉接收者即使在这个时候发信人也被冤枉了。
但是当我使用"sendmsg“时,将得到:未能发送消息:坏文件描述符
我的发件人代码如下:
int32_t SendFrame(const char *sockPath, char *sendFrameInfo, uint32_t sendFrameInfoLen,
int32_t inFd) {
int SockFd = socket(AF_UNIX, SOCK_DGRAM, 0);
struct sockaddr_un peer;
/* Create name. */
peer.sun_family = AF_UNIX;
strcpy(peer.sun_path, sockPath);
int ret = connect(SockFd, (struct sockaddr *)&peer, sizeof(struct sockaddr_un));
struct msghdr msg = {0};
struct cmsghdr *cmsg;
char buf[CMSG_SPACE(sizeof(int))];
memset(buf, '\0', sizeof(buf));
struct iovec io = {.iov_base = (void *)sendFrameInfo, .iov_len = sendFrameInfoLen};
msg.msg_iov = &io;
msg.msg_iovlen = 1;
msg.msg_control = buf;
msg.msg_controllen = sizeof(buf);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
memcpy((int *)CMSG_DATA(cmsg), &inFd, sizeof(int));
if (sendmsg(SockFd, &msg, 0) < 0) {
printf("SendFrame(%s) Failed to send message: %s", sockPath, strerror(errno));
return -1;
}
return 0;
};我的接收器代码如下:
int32_t recvFrame(char *buf, int32_t fd, uint32_t timeout_ms, uint32_t bufsize) {
struct msghdr msg = {0};
struct cmsghdr *cmsg;
char msg_control[CMSG_SPACE(sizeof(int))];
memset(msg_control, '\0', sizeof(msg_control));
struct iovec io = { .iov_base = &buf, .iov_len = bufsize };
msg.msg_iov = &io;
msg.msg_iovlen = 1;
msg.msg_control = msg_control;
msg.msg_controllen = sizeof(msg_control);
struct timeval timeout;
timeout.tv_sec = timeout_ms / 1000;
timeout.tv_usec = (timeout_ms % 1000) * 1000;
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
ssize_t len = recvmsg(fd, &msg, 0);
if (len < 0) {
perror("Failed to receive message");
return -errno;
}
cmsg = CMSG_FIRSTHDR(&msg);
int new fd = *((int32_t *)CMSG_DATA(cmsg));
return 0;
}现在我可以使用,所以我如何使用"msg_iov“来发送其他信息。因此,我希望接收消息事件发送者的fd是-1,然后我可以检查"msg_iov“发生了什么。
谢谢!
BR/Tim
发布于 2021-04-28 15:44:45
不,您只能传递有效的文件描述符,而且-1永远不是有效的文件描述符(因为当发生错误时会返回它)。
我建议的是在消息中包含一个特殊的字节( char ),描述错误--例如,作为消息中的第一个字符。如果传递文件描述符,则为零;如果发生错误,则为非零(描述错误的值)。这样,有效负载数据永远不会是零长度,这使得在发送任何数据之前更容易检测套接字关闭。(您知道,零长度读取/接收通常表示输入结束。)
因为errno值不一定在不同的机器上匹配,所以您应该将特定的字节值转换为errno代码,反之亦然。
或者,如果消息没有其他数据,则可以将错误消息作为字符串发送,包括结束时的'\0'字符串结束标记;在传递文件描述符时,只使用'\0'作为数据有效负载。
https://stackoverflow.com/questions/67302290
复制相似问题