Unix域中用于标识客户和服务端的协议地址是普通文件系统中的路径名。
struct sockaddr_un {
sa_family_t sun_family;
char sum_path[104]; /* null-terminated pathname */
}
#include "../myunp.h"
int main(int argc, char **argv)
{
int sockfd;
socklen_t len;
struct sockaddr_un addr1, addr2;
if (argc != 2) {
printf("usage: unix bind ");
return -1;
}
if ((sockfd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) {
printf("socket error: %s\n", strerror(errno));
return -1;
}
unlink(argv[1]); /* OK if this fails */
memset(&addr1, 0, sizeof(addr1));
addr1.sun_family = AF_LOCAL;
strncpy(addr1.sun_path, argv[1], sizeof(addr1.sun_path) - 1);
if (bind(sockfd, (struct sockaddr *)&addr1, sizeof(addr1)) < 0) {
printf("bind error: %s\n" strerror(errno));
return -1;
}
len = sizeof(addr2);
getsockname(sockfd, (struct sockaddr *)&addr2, &len);
printf("bound name = %s, returned len = %d\n", addr2.sun_path, len);
return 0;
}
(1)UDP
#include "../myunp.h"
void UdpClient(int sockfd, const SA *pservaddr, socklen_t servlen)
{
int n = 0;
char sendline[MAXLINE] = {0};
char recvline[MAXLINE + 1] = {0};
socklen_t len = 0;
struct sockaddr *preplyaddr = NULL;
while (fgets(sendline, MAXLINE, stdin) != NULL) {
if (sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen) < 0) {
printf("sendto error: %s\n", strerror(errno));
return;
}
len = servlen;
if ((n = recvfrom(sockfd, recvline, MAXLINE, 0, preplyaddr, &len)) < 0) {
printf("recvfrom error: %s\n", strerror(errno));
return;
}
recvline[n] = 0; /* null terminate */
fputs(recvline, stdout);
}
}
int main(int argc, char **argv)
{
int sockfd;
struct sockaddr_un servaddr;
struct sockaddr_un cliaddr;
if ((sockfd = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0) {
printf("sockfd error: %s\n", strerror(errno));
return -1;
}
memset(&cliaddr, '\0', sizeof(cliaddr));
cliaddr.sun_family = AF_LOCAL;
strcpy(cliaddr.sun_path, tmpnam(NULL));
/* bind an address for us */
if (bind(sockfd, (SA *)&cliaddr, sizeof(cliaddr)) < 0) {
printf("bind error: %s\n", strerror(errno));
return -1;
}
memset(&servaddr, '\0', sizeof(servaddr));
servaddr.sun_family = AF_LOCAL;
strcpy(servaddr.sun_path, UNIXDG_PATH);
UdpClient(sockfd, (SA *)&servaddr, sizeof(servaddr));
return 0;
}
#include "../myunp.h"
void UdpEcho(int sockfd, SA *pcliaddr, socklen_t clilen)
{
int n = 0;
socklen_t len = 0;
char msg[MAXLINE] = {0};
for ( ; ; ) {
len = clilen;
if ((n = recvfrom(sockfd, msg, MAXLINE, 0, pcliaddr, &len)) < 0) {
printf("recvfrom error: %s\n", strerror(errno));
return ;
}
if (sendto(sockfd, msg, n, 0, pcliaddr, len) < 0) {
printf("sendto error: %s\n", strerror(errno));
return ;
}
}
}
int main(int argc, int **argv)
{
int sockfd;
struct sockaddr_un servaddr;
struct sockaddr_un cliaddr;
if ((sockfd = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0) {
printf("socked error: %s\n", strerror(errno));
return -1;
}
unlink(UNIXDG_PATH);
memset(&servaddr, '\0', sizeof(servaddr));
servaddr.sun_family = AF_LOCAL;
strcpy(servaddr.sun_path, UNIXDG_PATH);
if (bind(sockfd, (SA *)&servaddr, sizeof(servaddr)) < 0) {
printf("bind error: %s\n", strerror(errno));
return -1;
}
UdpEcho(sockfd, (SA *)&cliaddr, sizeof(cliaddr));
}
(2)TCP
#include "../myunp.h"
#include
void StrCli(FILE *fp, int sockfd)
{
char sendline[MAXLINE] = {0};
char recvline[MAXLINE] = {0};
while (fgets(sendline, MAXLINE, fp) != NULL) {
writen(sockfd, sendline, strlen(sendline));
if (readline(sockfd, recvline, MAXLINE) == 0) {
printf("StrCli: server terminated prematurely\n");
return;
}
fputs(recvline, stdout);
}
}
int main(int argc, char **argv)
{
int sockfd;
struct sockaddr_un servaddr;
if ((sockfd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) {
printf("socket error\n");
return -1;
}
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sun_family = AF_LOCAL;
strcpy(servaddr.sun_path, UNIXSTR_PATH);
if ((connect(sockfd, (SA *)&servaddr, sizeof(servaddr))) < 0) {
printf("connect error: %s\n", strerror(errno));
return -1;
}
StrCli(stdin, sockfd); /* do it all */
return 0;
}
#include "../myunp.h"
#include
void sig_child(int signo)
{
pid_t pid;
int stat;
while ((pid = waitpid(-1, &stat, WNOHANG)) > 0) {
printf("child %d terminated\n", pid);
}
return;
}
void StrEcho(int sockfd)
{
ssize_t n = 0;
char buf[MAXLINE] = {0};
for ( ; ; ) {
while ((n = read(sockfd, buf, MAXLINE)) > 0) {
if (writen(sockfd, buf, n) != n) {
printf("writen error: %s\n", strerror(errno));
return ;
}
}
if (n < 0 && errno == EINTR) {
continue;
} else if (n < 0) {
printf("read error: %s\n", strerror(errno));
return ;
}
break;
}
}
int main()
{
int listenfd;
int connfd;
int optval = 1;
pid_t childpid;
socklen_t clilen;
struct sockaddr_un cliaddr;
struct sockaddr_un servaddr;
if ((listenfd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) {
printf("socket error: %s\n", strerror(errno));
return -1;
}
/* Eliminates "Address already in use" error from bind */
if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR,
(const void *)&optval, sizeof(optval)) < 0) {
printf("setsockopt error\n");
return -1;
}
unlink(UNIXSTR_PATH);
memset(&servaddr, '\0', sizeof(servaddr));
servaddr.sun_family = AF_LOCAL;
strcpy(servaddr.sun_path, UNIXSTR_PATH);
if (bind(listenfd, (SA *)&servaddr, sizeof(servaddr)) < 0) {
printf("bind error: %s\n", strerror(errno));
return -1;
}
if (listen(listenfd, LISTENQ) < 0) {
printf("listen error: %s\n", strerror(errno));
return -1;
}
signal(SIGCHLD, sig_child);
for ( ; ; ) {
clilen = sizeof(cliaddr);
if ((connfd = accept(listenfd, (SA *)&cliaddr, &clilen)) < 0) {
if (errno == EINTR) {
continue; /* back to for */
} else {
printf("accept error: %s\n", strerror(errno));
return -1;
}
}
if ((childpid = fork()) == 0) { /* child process */
close(listenfd); /* close listening socket */
StrEcho(connfd); /* process the request */
exit(0);
}
close(connfd); /* parent closes connected socket */
}
}
可以使用Unix域在进程间传递描述符。#include "../myunp.h"
int my_open(const char *, int);
ssize_t read_fd(int fd, void *ptr, size_t nbytes, int *recvfd);
int main(int argc, char **argv)
{
int fd, n;
char buff[BUFFSIZE] = { 0 };
if (argc != 2) {
printf("usage: mycat \n");
return -1;
}
if ((fd = my_open(argv[1], O_RDONLY)) < 0) {
printf("cannot open %s\n", argv[1]);
return -1;
}
while ((n = read(fd, buff, BUFFSIZE)) > 0) {
write(STDOUT_FILENO, buff, n);
}
exit(0);
}
int my_open(const char *pathname, int mode)
{
int fd, status;
int sockfd[2];
pid_t childpid;
char c;
char argsockfd[10] = { 0 };
char argmode[10] = { 0 };
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd) < 0) {
printf("socketpair error: %s\n", strerror(errno));
return -1;
}
if ((childpid = fork()) == 0) { /* child process */
close(sockfd[0]);
snprintf(argsockfd, sizeof(argsockfd), "%d", sockfd[1]);
snprintf(argmode, sizeof(argmode), "%d", mode);
execl("./openfile", "openfile", argsockfd, pathname, argmode, (char *)NULL);
printf("execl error: %s\n", strerror(errno));
return -1;
}
/* parent process - wait for the child to terminate */
close(sockfd[1]); /* close the end we don't use */
waitpid(childpid, &status, 0);
if (WIFEXITED(status) == 0) {
printf("child did not ternimate");
}
if ((status = WEXITSTATUS(status)) == 0) {
read_fd(sockfd[0], &c, 1, &fd);
} else {
errno = status; /* set errno value from child's status */
fd = -1;
}
close(sockfd[0]);
return fd;
}
ssize_t read_fd(int fd, void *ptr, size_t nbytes, int *recvfd)
{
struct msghdr msg;
struct iovec iov[1];
ssize_t n;
#ifdef HAVE_MSGHDR_MSG_CONTROL
union {
struct cmsghdr cm;
char control[CMSG_SPACE(sizeof(int))];
} control_un;
struct cmsghdr *cmptr;
msg.msg_control = control_un.control;
msg.msg_controllen = sizeof(control_un.control);
#else
int newfd;
msg.msg_accrights = (caddr_t)&newfd;
msg.msg_accrightslen = sizeof(int);
#endif
msg.msg_name = NULL;
msg.msg_namelen = 0;
iov[0].iov_base = ptr;
iov[0].iov_len = nbytes;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
if ((n = recvmsg(fd, &msg, 0)) <= 0) {
return n;
}
#ifdef HAVE_MSGHDR_MSG_CONTROL
if ((cmptr = CMSG_FIRSTHDR(&msg)) != NULL
&& cmptr->cmsg_len == CMSG_LEN(sizeof(int))) {
if (cmptr->cmsg_level != SOL_SOCKET) {
printf("control level != SOL_SOCKET\n");
return -1;
}
if (cmptr->cmsg_type != SCM_RIGHTS) {
printf("control type != SCM_RIGHTS\n");
return -1;
}
*recvfd = *((int *)CMSG_DATA(cmptr));
} else {
*recvfd = -1; /* descriptor was not passed*/
}
#else
if (msg.msg_accrightslen == sizeof(int)) {
*recvfd = newfd;
} else {
*recvfd = -1; /* descriptor was not passed */
}
#endif
return n;
}
#include "../myunp.h"
ssize_t write_fd(int fd, void *ptr, size_t nbytes, int sendfd);
int main(int argc, char **argv)
{
int fd;
if (argc != 4) {
printf("openfile ");
return -1;
}
if ((fd = open(argv[2], atoi(argv[3]))) < 0) {
exit((errno > 0) ? errno : 255);
}
if (write_fd(atoi(argv[1]), "", 1, fd) < 0) {
exit((errno > 0) ? errno : 255);
}
exit(0);
}
ssize_t write_fd(int fd, void *ptr, size_t nbytes, int sendfd)
{
struct msghdr msg;
struct iovec iov[1];
#ifdef HAVE_MSGHDR_MSG_CONTROL
union {
struct cmsghdr cm;
char control[CMSG_SPACE(sizeof(int))];
} control_un;
struct cmsghdr *cmptr;
msg.msg_control = control_un.control;
msg.msg_controllen = sizeof(control_un.control);
cmptr = CMSG_FIRSTHDR(&msg);
cmptr->cmsg_len = CMSG_LEN(sizeof(int));
cmptr->cmsg_level = SOL_SOCKET;
cmptr->cmsg_type = SCM_RIGHTS;
*((int *)CMSG_DATA(cmptr)) = sendfd;
#else
msg.msg_accrights = (caddr_t)&sendfd;
msg.msg_accrightslen = sizeof(int);
#endif
msg.msg_name = NULL;
msg.msg_namelen = 0;
iov[0].iov_base = ptr;
iov[0].iov_len = nbytes;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
return (sendmsg(fd, &msg, 0));
}