帶有非同步通知的進程間通訊

帶有非同步通知的進程間通訊

我嘗試設定兩個守護進程,一個客戶端和一個伺服器,伺服器分析一些系統統計訊息,並以非阻塞方式等待接收 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;

相關內容