클라이언트와 서버라는 두 개의 데몬을 설정하려고 하는데 서버가 일부 시스템 통계를 프로파일링하고 SIGIO가 수신될 때까지 비차단 방식으로 기다립니다. 그러면 SIGIO는 전송된 데이터를 읽고 다시 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으로 설정합니다.