下面是unix domain socket的服务器端和客户端的两个代码。
和internet的socket区别有
1. 使用AF_UNIX 而不是AF_INET
2. unix domain socket在bind时会生成一个文件,而AF_INET不会。
所以需要手动删除,否则不能bind成功。
/*
* =====================================================================================
*
* Filename: unix_socket_serv.c
*
* Description:
*
* Version: 1.0
* Created: 09/09/2010 08:26:42 PM
* Revision: none
* Compiler: gcc
*
* Author: YOUR NAME (),
* Company:
*
* =====================================================================================
*/
#include <apue.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#include <time.h>
#define QLEN 10
#define STALE 30
int
serv_listen1(const char *name)
{
int fd, len, err, rval;
struct sockaddr_un un;
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
return -1;
unlink(name); /* in case it already exists */
memset(&un, 0, sizeof(un));
un.sun_family = AF_UNIX;
strcpy(un.sun_path, name);
len = offsetof(struct sockaddr_un, sun_path) + strlen(name);
if (bind(fd, (struct sockaddr *)&un, len) < 0)
{
rval = -2;
goto errout;
}
if (listen(fd, QLEN) < 0)
{
rval = -3;
goto errout;
}
return fd;
errout:
err = errno;
close(fd);
errno = err;
return rval;
}
int
serv_accept1(int listenfd, uid_t *uidptr)
{
int clifd, len, err, rval;
time_t staletime;
struct sockaddr_un un;
struct stat statbuf;
len = sizeof(un);
if ((clifd = accept(listenfd, (struct sockaddr *)&un, &len)) < 0)
return -1;
len -= offsetof(struct sockaddr_un, sun_path);
un.sun_path[len] = 0;
if (stat(un.sun_path, &statbuf) < 0)
{
rval = -2;
goto errout;
}
#ifdef S_ISSOCK
if (S_ISSOCK(statbuf.st_mode) == 0)
{
rval = -3;
goto errout;
}
#endif
if ((statbuf.st_mode & (S_IRWXG | S_IRWXO)) ||
(statbuf.st_mode & S_IRWXU) != S_IRWXU)
{
rval = -4; /* is not rwx------ */
goto errout;
}
staletime = time(NULL) - STALE;
if (statbuf.st_atime < staletime ||
statbuf.st_ctime < staletime ||
statbuf.st_mtime < staletime )
{
rval = -5; /* i-node is too old */
goto errout;
}
if (uidptr != NULL)
*uidptr = statbuf.st_uid;
unlink(un.sun_path);
return clifd;
errout:
err = errno;
close(clifd);
errno = err;
return rval;
}
int
main()
{
int socket;
int conn;
uid_t uid;
char buf[1024];
socket = serv_listen1("unix_serv");
conn = serv_accept1(socket, &uid);
printf("uid: %d/n", uid);
read(conn, buf, 1024);
printf("%s/n", buf);
return 0;
}
/*
* =====================================================================================
*
* Filename: unix_socket_client.c
*
* Description:
*
* Version: 1.0
* Created: 09/09/2010 08:30:48 PM
* Revision: none
* Compiler: gcc
*
* Author: YOUR NAME (),
* Company:
*
* =====================================================================================
*/
#include <apue.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#define CLI_PATH "/var/tmp/"
#define CLI_PERM S_IRWXU
int
cli_conn1(const char *name)
{
int fd, len, err, rval;
struct sockaddr_un un;
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
return -1;
/* fill socket address structure with out address */
memset(&un, 0, sizeof(un));
un.sun_family = AF_UNIX;
sprintf(un.sun_path, "%s%05d", CLI_PATH, getpid());
len = offsetof(struct sockaddr_un, sun_path) + strlen(un.sun_path);
unlink(un.sun_path);
if (bind(fd, (struct sockaddr *)&un, len) < 0)
{
rval = -2;
goto errout;
}
if (chmod(un.sun_path, CLI_PERM) < 0)
{
rval = -3;
goto errout;
}
/* fill socet address structure with server's address */
memset(&un, 0, sizeof(un));
un.sun_family = AF_UNIX;
strcpy(un.sun_path, name);
len = offsetof(struct sockaddr_un, sun_path) + strlen(un.sun_path);
if (connect(fd, (struct sockaddr *)&un, len) < 0)
{
rval = -4;
goto errout;
}
return fd;
errout:
err = errno;
close(fd);
errno = err;
return rval;
}
int
main()
{
int fd;
fd = cli_conn1("unix_serv");
if (fd < 0)
{
err_quit("client error:");
}
write(fd, "test", 4);
return 0;
}