PTHREAD_PROCESS_SHARED
attributepipe()
mkfifo()
socketpair(AF_UNIX, ... )
socket(AF_UNIX, ... )
reliable when used in datagram mode
int socketpair(int domain, int type, int protocol, int sv[2]);
// Returns 0 if OK, -1 on error
Same picture as the one for pipe()
but arrows going both ways:
recv-unix.c
:
static void die(const char *m) { perror(m); exit(1); }
void handle_sigint(int signo) {}
int main(int argc, char **argv)
{
struct sigaction sa;
sa.sa_handler = &handle_sigint;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGINT, &sa, NULL) != 0) {
die("sigaction");
}
if (argc != 2) {
fprintf(stderr, "usage: %s <num-chars>\n", argv[0]);
exit(1);
}
int num_to_recv = atoi(argv[1]);
int fd;
struct sockaddr_un un, clnt_un;
socklen_t len, clnt_len;
char *name = "serv-dom-sock";
assert(strlen(name) < sizeof(un.sun_path));
// create a UNIX domain datagram socket
if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
die("socket failed");
// remove the server domain socket file if exists already
unlink(name);
// fill in the server domain socket address structure
memset(&un, 0, sizeof(un));
un.sun_family = AF_UNIX;
strcpy(un.sun_path, name);
len = offsetof(struct sockaddr_un, sun_path) + strlen(name);
// bind the server domain socket name to the descriptor
if (bind(fd, (struct sockaddr *)&un, len) < 0)
die("bind failed");
char *buf = malloc(num_to_recv + 1);
char reply[100];
int i = 0, n;
for (;;) {
memset(buf, 0, num_to_recv + 1);
clnt_len = sizeof(clnt_un);
n = recvfrom(fd, buf, num_to_recv, 0,
(struct sockaddr *) &clnt_un, &clnt_len);
if (n < 0) {
if (errno == EINTR)
break;
else
die("recvfrom failed");
}
fprintf(stderr, "\"%s\" received from ", buf);
write(STDERR_FILENO, clnt_un.sun_path,
clnt_len - offsetof(struct sockaddr_un, sun_path));
fprintf(stderr, " (clnt_len:%d), ", clnt_len);
snprintf(reply, sizeof(reply), "[%d](%s)", ++i, buf);
n = sendto(fd, reply, strlen(reply), 0,
(struct sockaddr *) &clnt_un, clnt_len);
if (n != strlen(reply)) {
die("sendto failed");
}
fprintf(stderr, "sent back %d bytes: %s\n", n, reply);
}
// Clean up
fprintf(stderr, "Server shutting down\n");
free(buf);
close(fd);
unlink(name);
}
send-unix.c
:
static void die(const char *m) { perror(m); exit(1); }
int main(int argc, char **argv)
{
if (argc != 3) {
fprintf(stderr, "usage: %s <msg> <num-repeat>\n", argv[0]);
exit(1);
}
const char *msg = argv[1];
int num_repeat = atoi(argv[2]);
int fd;
socklen_t my_len;
struct sockaddr_un my_un;
char my_name[sizeof(my_un.sun_path)];
snprintf(my_name, sizeof(my_name), "clnt-dom-sock.%d", getpid());
// create a UNIX domain datagram socket
if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
die("socket failed");
// fill in my own domain socket address structure
memset(&my_un, 0, sizeof(my_un));
my_un.sun_family = AF_UNIX;
strcpy(my_un.sun_path, my_name);
my_len = offsetof(struct sockaddr_un, sun_path) + strlen(my_name);
// bind my own domain sock name to the descriptor
if (bind(fd, (struct sockaddr *)&my_un, my_len) < 0)
die("bind failed");
socklen_t serv_len;
struct sockaddr_un serv_un;
char *serv_name = "serv-dom-sock";
assert(strlen(serv_name) < sizeof(serv_un.sun_path));
// fill in the server's domain socket address structure
memset(&serv_un, 0, sizeof(serv_un));
serv_un.sun_family = AF_UNIX;
strcpy(serv_un.sun_path, serv_name);
serv_len = offsetof(struct sockaddr_un, sun_path) + strlen(serv_name);
int i, n;
// send messages
for (i = 0; i < num_repeat; i++) {
n = sendto(fd, msg, strlen(msg), 0,
(struct sockaddr *) &serv_un, serv_len);
if (n != strlen(msg))
die("sendto failed");
else
fprintf(stderr, "[%d] sent %d bytes: \"%s\"\n", i+1, n, msg);
}
// receive replies
char reply[100];
for (i = 0; i < num_repeat; i++) {
memset(reply, 0, sizeof(reply));
n = recvfrom(fd, reply, sizeof(reply), 0, NULL, NULL);
if (n < 0)
die("recvfrom failed");
else
fprintf(stderr, "%d bytes received: \"%s\"\n", n, reply);
}
// clean up
close(fd);
unlink(my_name);
}
Duplicate a file descriptor across running processes:
Last updated: 2023-02-21