使用异步通知进行进程间通信

使用异步通知进行进程间通信

我尝试设置两个守护进程,一个客户端和一个服务器,服务器分析一些系统统计信息,并以非阻塞方式等待接收 SIGIO,然后它将读取发送给它的数据,将一些内容发送回客户端并继续执行正在执行的操作。

但是,客户端在其套接字上发出了阻塞发送和接收函数。我已经编写了相当多的代码,并广泛阅读,但似乎人们在尝试实现这种行为时使用了很多不同的范例,我真的很感激一些帮助,这是我目前的代码:

服务器:

  int s, s2, flags, n;
  struct sockaddr_un addr;
  struct sockaddr_un from;
  int from_len;
  socklen_t len;

  void message_received_helper(int sig){
  syslog(LOG_NOTICE, "Works! \n");
  }

  ...

    int main(int argc, char *argv[]) {

    deamonize();

    /* Daemon-specific initialization goes here */
setlogmask (LOG_UPTO (LOG_NOTICE));

openlog ("i_aware", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);

    syslog (LOG_NOTICE, "Program started by User %d", getuid ());

/*
 * This set up is for the non blocking socket that will exist on the server
 */
/* specify the new action for the SIGIO signal */
new_action.sa_handler = message_received_helper;
/* supply the empty set to .sa_mask */
sigemptyset(&new_action.sa_mask);
/* no flags*/
new_action.sa_flags = 0;
/* Associate new_action with the signal SIGIO -
 NULL indicates we are not saving any previous action*/
if(sigaction(SIGIO, &new_action, NULL) < 0 ){
    syslog(LOG_NOTICE, "Could not associate SIGIO with action...\n");
    exit(errno);
}

/*TODO create unix domain socket and listen for a connection*/
if((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0 ){
    syslog(LOG_NOTICE, "Could not create socket: %d \n", errno);
    perror("socket");
    exit(errno);

}

/* bind socket */
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, "/dev/foo");
unlink(addr.sun_path);
len = (socklen_t) (strlen(addr.sun_path) + sizeof(addr.sun_family));

if( bind(s, (struct sockaddr *) &addr,len ) == -1){
    syslog(LOG_NOTICE, "Could not bind socket %d \n", errno);
    perror("bind");
    exit(errno);

}
/* listen */
if(listen(s, 1) < 0){
    syslog(LOG_NOTICE,"Error on listen: %d \n", errno);
    perror("listen");
    exit(errno);        

}
from_len = sizeof(from);
if(s2 = accept(s,  (struct sockaddr *) &from, &from_len ) < 0 ){
    syslog(LOG_NOTICE,"Error on accept: %d \n", errno);
    perror("accept");
    exit(errno);

}
syslog(LOG_NOTICE,"success \n");

/* set the ownership of the socket fd to this process */
syslog(LOG_NOTICE, "F_SETOWN: %d \n" ,fcntl(s2, F_SETOWN, getpid()) );  
/*get file access mode and file status flag - no args needed for this F_GETFL comand*/
flags  = fcntl(s2, F_GETFL);
syslog(LOG_NOTICE, "F_GETFL: %d \n", flags);
/* Enable non blocking */
syslog(LOG_NOTICE, "F_SETFL: %d \n" , fcntl(s2, F_SETFL, flags | FASYNC));

/*
 * At this point the socket described by s2, should be a non blocking socket, when a SIGIO
 * is raised upon receipt of data waiting on the socket the method message_received_helper
 * will be called 
 */ 
n = recv(s2, str, 1, 0);
syslog(LOG_NOTICE, "Works! \n");

if (n <= 0) {
           if (n < 0) syslog(LOG_NOTICE, "recv error: %d", errno);
        }
        syslog(LOG_NOTICE, "n: %d, s2: %d, str: %s \n", n, s2, str );


    if (send(s2, str, n, 0) < 0) {
            syslog(LOG_NOTICE, "send: %d", errno);

            }

客户:

int s, s2, t, len;
struct sockaddr_un local, remote;
char str[100];

if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
    perror("socket");
    exit(1);
}

local.sun_family = AF_UNIX;
strcpy(local.sun_path, SOCK_PATH);
unlink(local.sun_path);
len = strlen(local.sun_path) + sizeof(local.sun_family);
if (bind(s, (struct sockaddr *)&local, len) == -1) {
    perror("bind");
    exit(1);
}

if (listen(s, 5) == -1) {
    perror("listen");
    exit(1);
}

for(;;) {
    int done, n;
    printf("Waiting for a connection...\n");
    t = sizeof(remote);
    if ((s2 = accept(s, (struct sockaddr *)&remote, &t)) == -1) {
        perror("accept");
        exit(1);
    }

    printf("Connected.\n");

    done = 0;
    do {
        n = recv(s2, str, 100, 0);
        if (n <= 0) {
            if (n < 0) perror("recv");
            done = 1;
        }

        if (!done) 
            if (send(s2, str, n, 0) < 0) {
                perror("send");
                done = 1;
            }
    } while (!done);

    close(s2);

两个进程能够通过套接字连接,但客户端向服务器发送数据时不会引发 SIGIO。此外,recv() 函数一直处于阻塞状态,好像我没有做任何事来影响套接字 s2 以使读取不阻塞。

答案1

if(s2 = accept(s,  (struct sockaddr *) &from, &from_len ) < 0 ) 

不正确,应为

if( (s2 = accept(s,  (struct sockaddr *) &from, &from_len )) < 0 )

缺少括号使得第一个语句读作s2 = < 0,将 s2 设置为 0;

相关内容