【发布时间】:2017-02-20 15:58:34
【问题描述】:
我有一个 while(1) 循环,它使用 recvfrom 获取已从另一个进程 (P2) 发送到域套接字的数据。
while循环需要做两件事,首先监听来自P2的传入数据,其次运行另一个函数checkVoltage()。
所以它的运行有点像这样:
while(true)
{
listenOnSocket() /*listens for 100 u seconds*/
checkVoltage();
}
我的问题是:listenOnSocket() 函数使用recvfrom 函数来检查来自另一个进程的输入。它花费 100usecs 监听,然后超时并继续运行 checkVoltage() 函数。所以它在listenOnSocket() 函数中花费了大约 99% 的时间。我的问题是,如果 P2 在 checkVoltage() 函数期间向套接字发送信息,则会导致错误,说明:sending datagram message: No such file or directory。
有没有办法让这个循环检查以前发送到套接字的任何数据?这样如果P2在checkVoltage()函数中发送数据,就不会报错。
谢谢。
编辑:
所以listenOnSocket() 函数创建了一个名为FireControl 的套接字,当我运行P1(从P2 接收数据的程序)时,FireControl 文件消失了片刻然后又重新出现。如果 P2 在这短时间内向 P1 发送数据,则会导致上面提到的错误。
所以我想这意味着我应该将套接字的创建与recvfrom 函数分开,因为创建新套接字的时间很短 - 如果这有意义的话。
我是个笨蛋,我一开始就应该把他们分开!
EDIT2:这里是listenOnSocket():
command listenOnSocket(int timeout, float utimeout) /*Returns null payload when no input is detected*/
{
command payload;
int sock;
socklen_t* length;
struct sockaddr_un name;
char buf[1024];
struct timeval tv;
tv.tv_sec = timeout;
tv.tv_usec = utimeout;
/* Create socket from which to read. */
sock = socket(AF_UNIX, SOCK_DGRAM, 0);
if (sock < 0)
{
perror("opening datagram socket");
payload = nullPayload;
}
/* Create name. */
name.sun_family = AF_UNIX;
strcpy(name.sun_path, NAME);
unlink(name.sun_path);
/* Bind the UNIX domain address to the created socket */
if (bind(sock, (struct sockaddr *) &name, sizeof(struct sockaddr_un)))
{
perror("binding name to datagram socket\n");
payload = nullPayload;
}
/*Socket has been created at NAME*/
if (timeout != 0 || utimeout != 0)
{
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval));
}
else
{
tv.tv_sec = 0;
tv.tv_usec = 0;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval));
}
/* Read from the socket */
if (recvfrom(sock, &payload, sizeof(command), 0, (struct sockaddr *)&name, &length) < 0) /*Less than zero results from a timeout*/
{
payload = nullPayload;
}
unlink(NAME);
return payload;
}
这是调用它的循环:
while (1)
{
buffer = getADCValue();
checkVoltage();
temp = listenOnSocket(0, 100); /*Look for a new command*/
doStuffWithTempIfItHasChanged();
}
}
【问题讨论】:
-
"sent to a domain socket" -> 给定标签,我可以假设你的意思是 UNIX 域套接字吗?
-
另外,您确定您的套接字完全可以工作吗? AFAIK,你不应该被困在
recvfrom中以使 P2 的send/sendto调用成功完成,如果套接字确实存在,则消息应该排队。 -
@zneak 是的,这是一个 unix 域套接字(在 Raspbian 上运行)。套接字确实可以工作,在另一段代码中我运行
listenOnSocket没有任何超时,并且程序在等待输入时位于recvfrom函数上。 -
现在向问题添加更多信息
-
这是您问题的根源。
listenOnsocket()总是删除并创建一个新的套接字。您应该只在输入服务器代码时创建一次套接字,然后在recvfrom()上循环。这个创建和删除循环将丢弃任何在套接字中排队的东西。
标签: c sockets unix-socket