0

如果这个问题已经响起,我很抱歉 - 找不到......所以我有计时器:

bzero(&rtc_act, sizeof(struct sigaction));
rtc_act.sa_handler = &rtc_handler;
sigaction(SIGALRM, &rtc_act, NULL);

rtc_timer.it_interval.tv_sec = SETTIMER_INTERVAL;
rtc_timer.it_interval.tv_usec = 0;
rtc_timer.it_value.tv_sec = SETTIMER_VALUE;
rtc_timer.it_value.tv_usec = 0;

if (setitimer(ITIMER_REAL, &rtc_timer, NULL))
{
    printf(MSG_ERR_SETTIMER_FAIL);
    retval = RETURN_ERR_SETTIMER;
} /* if (setitimer(ITIMER_REAL, &rtc_timer, NULL)) */

我也阻塞了套接字:

if ((modbus_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
    retval = RETURN_ERR_SOCKET_OPEN;
    perror(MSG_ERR_OPEN_SOCKET);
    return retval;
} /* if (modbus_socket = socket(AF_INET, SOCK_STREAM, 0) < 0) */

setsockopt(modbus_socket, SOL_SOCKET, SO_REUSEADDR, (const void*)&optval , sizeof(unsigned int));

bzero((char*)&serv_addr, sizeof(serv_addr));

serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons((unsigned short)ZK91_TCP_PORT_NUMBER);

if (bind(modbus_socket, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
{
    perror(MSG_ERR_BIND_SOCKET);
    retval = RETURN_ERR_SOCKET_OPEN;
    return retval;
} /* if (bind(modbus_socket, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) */

if (listen(modbus_socket, TCP_CLIENTS_COUNT) < 0)
{
    perror(MSG_ERR_LISTEN_SOCKET);
    retval = RETURN_ERR_SOCKET_LISTEN;
    return retval;
} /* if (listen(parentfd, TCP_CLIENTS_COUNT) < 0) */

当我尝试使用 select()

    FD_ZERO(&fds);
    FD_SET(modbus_socket, &fds);
    FD_SET(can_file, &fds);
    FD_SET(modbus_file, &fds);

    select(modbus_file + 1, &fds, NULL, NULL, &tv);

尽管实际数据不可用,但我在几秒钟内得到了激活 select()。

如果您尝试处理此“连接”:

new_socket = 接受 (modbus_socket, (struct sockaddr *) & client_addr, & client_len);

然后程序崩溃,给屏幕 10 个字符,然后是一些内存区域:

网络来了(我的消息)

������砗����L�</p>

uclinux#

如果我不初始化计时器,那么一切正常,但在计时器上我不能拒绝。

可能是什么原因?

谢谢你。

4

2 回答 2

1

您需要检查errno是否select()失败并忽略它的SIGALRM中断。

就像是:

for (;;) {
    int rv = select(...);
    if (rv < 0) {
        if (errno == EINTR)
            continue;    // Was a signal
        else
            // A real error occurred
    } else {
        // Handle event
    }
}
于 2013-07-08T12:12:13.570 回答
0

您必须在退货后检查select()退货的原因。您不能不检查就假设它在说“套接字准备好读取”。

检查是使用FD_ISSET()宏完成的,以查看套接字文件描述符是否仍在准备读取集中。

如果select()是因为被中断而返回,它也将设置errnoEINTR, 并返回 -1。由于它通常返回三个输入集中的集合描述符的数量,因此您也应该检查返回值。FD_ISSET()除非select()返回大于 0 的值,否则无需开始调用。

于 2013-07-08T12:07:47.423 回答