Estou tentando configurar dois daemons, um cliente e um servidor, o servidor traça o perfil de algumas estatísticas do sistema e aguarda de forma não bloqueadora o recebimento de um SIGIO, após o qual irá ler os dados enviados a ele, enviar algo de volta para o cliente e continuar com o que quer que estivesse fazendo.
No entanto, o cliente emite bloqueio de funções de envio e recebimento em seu soquete. Eu fiz bastante codificação e li bastante, mas parece que há muitos paradigmas diferentes que as pessoas usam quando tentam alcançar esse tipo de comportamento. Eu realmente apreciaria alguma ajuda, aqui está meu código até agora:
SERVIDOR:
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);
}
CLIENTE:
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);
Os dois processos conseguem se conectar pelo soquete, mas nenhum SIGIO é gerado quando o cliente envia dados ao servidor. Além disso, a função recv() continua bloqueando, como se nada do que eu tenha feito afetasse o soquete s2 para tornar as leituras sem bloqueio.
Responder1
if(s2 = accept(s, (struct sockaddr *) &from, &from_len ) < 0 )
está incorreto, deve ser lido
if( (s2 = accept(s, (struct sockaddr *) &from, &from_len )) < 0 )
Os parênteses faltantes fizeram a primeira declaração ser lidas2 = < 0, que definiu s2 como 0;