1.UNIX 域套接字域 TCP 套接字相比,在同一台主机的传输速度前者是后者的两倍
。UNIX 域套接字仅仅复制数据,并不执行协议处理,不需要添加或删除网络报头,无需计算校验和,不产
生顺序号,也不需要发送确认报文
2.UNIX 域套接字可以在同一台主机上各进程之间传递文件描述符
3.UNIX 域套接字域传统套接字的区别是用路径名表示协议族的描述
UNIX 域协议地址
#define UNIX_PATH_MAX 108
__kernel_sa_family_t sun_family;
char sun_path[UNIX_PATH_MAX];
UNIX 域协议用于本地进程间通信的编程流程和 TCP/UDP 一样,只不过具体的协议地址是使
用文件路径名
Server:先创建套接字 -> 绑定地址 -> 监听 -> accept 客户端连接 -> 连接成功开始通信 -> 关闭套接字
Client:先创建套接字 ->绑定地址-> 连接 server -> 开始通信 -> 关闭套接字。
UNIX 域协议之进程间通信方式一:socketpair 函数
【函数原型】
int socketpair(int domain, int type, int protocol, int sv[2]);
【函数功能】
此函数只用于 Unix 域套接口,它的 domain 必须是 AF_LOCAL,protocol 参数必须为 0,type 可以是 SOCK_STREAM 也可以是 SOCK_DGRAM,它与调用 pipe 创建的普通管道类似,差别在 于普通管道只能进行单向读或单向写,而该管道是全双工的,可以单向读写。
【参数含义】
[domain]: 表示协议族,在 Linux 下只能为
AF_LOCAL
或者
AF_UNIX
。(自从 Linux 2.6.27 后也支持 SOCK_NONBLOCK 和 SOCK_CLOEXEC)
[type]: 表示协议,可以是 SOCK_STREAM 或者 SOCK_DGRAM。SOCK_STREAM 是基于TCP 的,而 SOCK_DGRAM 是基于 UDP 的
[protocol]: 表示类型,只能为 0
[sv]: 套节字柄对,该两个句柄作用相同,均能进行读写双向操作
【返回值】
0 为创建成功,-1 为创建失败,并且 errno 来表明特定的错误号,具体错误号如下所述:
EAFNOSUPPORT:本机上不支持指定的 address。
EFAULT:
地址 sv 无法指向有效的进程地址空间内。
EMFILE: 已经达到了系统限制文件描述符,或者该进程使用过量的描述符。
EOPNOTSUPP:指定的协议不支持创建套接字对。
EPROTONOSUPPORT:本机不支持指定的协议。
【备注】
1、该函数只能用于
UNIX
域(
LINUX
)下。
2、只能用于有亲缘关系的进程(或线程)间通信。
3、所创建的套节字对作用是一样的,均能够可读可写(而管道
PIPE
只能进行单向读写)。
4、在读的时候,管道内必须有内容,否则将会阻塞;简而言之,该函数是阻塞的。
【示例代码】
int result = socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
printf("sv[0] is : %d \n", sv[0]);
printf("sv[1] is : %d \n", sv[1]);
printf("%d send message: %d\n", pid, val);
write(sv[0], &val, sizeof(val));
read(sv[1], &val, sizeof(val));
printf("%d receive message: %d\n", pid, val);
UNIX 域协议之进程间通信方式二:套接字通信方式
UNIX 域协议进行本地通信的方式和 TCP、UDP 很类似,下面就以 UNIX 域协议的流式套接字来写一个客户端和服务器间通信的例子,使用流式套接字,则本地间的通信方式就要类似于 TCP,这样的通信方式同时也具有 TCP 通信的特点。
客户端示例程序:
#define UNIX_PATH_PS "/home/china/sockp1"
#define UNIX_PATH_PC "/home/china/sockp2"
int main(int argc,char *argv[])
system("rm /home/china/sockp2");
int sockfd = socket(AF_UNIX, SOCK_STREAM,0);
perror("create socket failed");
struct sockaddr_un local;
memset(&local,0,sizeof(struct sockaddr_un));
local.sun_family = AF_UNIX;
strcpy(local.sun_path,UNIX_PATH_PC);
int ret = bind(sockfd,(struct sockaddr*)&local,sizeof(local));
printf("bind success\n");
struct sockaddr_un saddr;
memset(&saddr,0,sizeof(struct sockaddr_un));
saddr.sun_family = AF_UNIX;
strcpy(saddr.sun_path,UNIX_PATH_PS);
ret = connect(sockfd, (struct sockaddr*)&saddr,sizeof(saddr));
printf("connect success\n");
ret = recv(sockfd,buf,1024, 0);
printf("recv size:%d,recv data:%s\n",ret,buf);
ret = sendto(sockfd,"byebye",6,0,NULL,0);
printf("sendto size:%d\n",ret);
shutdown(sockfd,SHUT_RDWR);

服务器程序示例:
#define UNIX_PATH_PS "/home/china/sockp1"
int main(int argc,char *argv[])
system("rm /home/china/sockp1");
int sockfd = socket(AF_UNIX, SOCK_STREAM,0);
perror("create socket failed");
struct sockaddr_un local;
memset(&local,0,sizeof(struct sockaddr_un));
local.sun_family = AF_UNIX;
strcpy(local.sun_path,UNIX_PATH_PS);
int ret = bind(sockfd,(struct sockaddr*)&local,sizeof(local));
printf("bind success\n");
struct sockaddr_un caddr;
socklen_t len = sizeof(caddr);
int confd = accept(sockfd,(struct sockaddr*)&caddr,&len);
printf("client path:%s\n",caddr.sun_path);
ret = sendto(confd,"nishiliangzaima?",20,0,NULL,0);
ret = read(confd,buf,1024);
printf("recv size:%d,recv data:%s\n",ret,buf);
shutdown(sockfd,SHUT_RDWR);
