Unix 도메인 소켓(IPC 소켓이라고도 함)을 통해 하위 프로세스(서버)와 통신하는 상위 프로세스(클라이언트)가 있습니다.
소켓은 socketpair()
데이터그램 유형을 사용하여 생성됩니다.
나는 posix_spawn()
하위 프로세스를 시작하고 close()
상위-하위 프로세스에서 필요하지 않은 소켓 쌍의 끝을 시작하는 데 사용합니다.
아이들과 함께 사용 poll()
하고 recv()
.
이것은 모두 좋습니다.
이제 클라이언트가 소켓 끝을 닫거나 클라이언트가 종료될 때 하위(서버)에 알림이 전달되기를 원합니다.
에서 POLLHUP
또는 POLLERR
이벤트를 받기를 바랐 close()
지만 아무 것도 얻지 못했습니다.
열려 있는 2개의 프로세스를 나열하는 Unix 도메인 소켓을 사용할 때 lsof -U
소켓의 다른 쪽 끝은 none
클라이언트가 종료된 후임을 알 수 있습니다.
중요한 경우 이는 macOS에 있습니다.
내가 무엇을 놓치고 있나요? 클라이언트가 Unix 도메인 소켓을 닫을 때 어떻게 알림을 받나요?
답변1
귀하의 설명을 바탕으로 샘플 앱을 구성했지만 약간의 차이가 있습니다. 첫째, SOCK_STREAM
대신 을 사용했습니다 SOCK_DGRAM
. 이 변경으로 인해 POLLHUP
소켓이 더 이상 연결 SOCK_DGRAM
지향 소켓이 아니라는 의미입니다. 사용하는 이유가 있나요 SOCK_DGRAM
?
이 예제와 설명하는 예제 의 두 번째 작은 차이점은 fork()
내가 posix_spawn()
.fork()
#include <poll.h>
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
int main(void)
{
int sockets[2] = {};
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0) {
perror("socketpair");
return 1;
}
const pid_t pid = fork();
if (pid < 0) {
perror("fork");
return 2;
}
if (pid > 0) {
/* parent */
close(sockets[0]);
sockets[0] = 0;
for (int i = 0; i < 3; ++i) {
write(sockets[1], "hello", sizeof("hello"));
sleep(2);
}
/* sockets[1] will get closed on parent termination */
return 0;
}
/* child */
close(sockets[1]);
sockets[1] = 0;
struct pollfd fds = {
.fd = sockets[0],
.events = POLLIN | POLLHUP,
};
while (poll(&fds, 1, 10 * 1000) > 0) {
if (fds.revents & POLLHUP) {
printf("--- Received hangup\n");
break;
}
if (fds.revents & POLLERR) {
printf("!!! Received error\n");
break;
}
if (fds.revents & POLLIN) {
char buffer[32] = {};
if (recv(sockets[0], buffer, sizeof buffer, 0) < 0) {
perror("recv");
return 3;
}
printf("--> Received message '%s'\n", buffer);
}
}
/* sockets[0] will get closed on child termination */
return 0;
}
이 프로그램에서 부모는 자식에게 메시지를 씁니다. 자식 프로세스는 이러한 메시지를 받아 처리합니다(여기서는 표준 출력으로 인쇄합니다). 상위 프로세스는 3개의 메시지를 보낸 후 종료됩니다.
이 프로그램을 실행하면 여러분이 찾고 있다고 생각되는 동작이 보입니다.
$ ./a.out
--> Received message 'hello'
--> Received message 'hello'
--> Received message 'hello'
--- Received hangup
반드시 사용해야 한다면 SOCK_DGRAM
.에 대한 호출은 poll()
결국 시간 초과됩니다(제 예에서는 시간 초과가 10초였습니다). 이벤트에 대한 클라이언트 프로세스를 종료할 수 있습니다.