linux网络编程之socket(十五) UNIX域套接字编程和socketpair 函数
|
一、UNIX Domain Socket IPC
socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机 制,就是UNIX Domain Socket。虽然网络socket也可用于同一台主机的进程间通讯(通过loopback地址127.0.0.1),但是 UNIX Domain Socket用于IPC更有效率:不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是 将应用层数据从一个进程拷贝到另一个进程。UNIX域套接字与TCP套接字相比较,在同一台主机的传输速度前者是后者的两 倍。这是因为,IPC机制本质上是可靠的通讯,而网络协议是为不可靠的通讯设计的。UNIX Domain Socket也提供面向流和 面向数据包两种API接口,类似于TCP和UDP,但是面向消息的UNIXDomain Socket也是可靠的,消息既不会丢失也不会顺序错 乱。 使用UNIX Domain Socket的过程和网络socket十分相似,也要先调用socket()创建一个socket文件描述符, address family指定为AF_UNIX,type可以选择SOCK_DGRAM或SOCK_STREAM,protocol参数仍然指定为0即可。 UNIX Domain Socket与网络socket编程最明显的不同在于地址格式不同,用结构体sockaddr_un表示,网络编程的socket地址是IP 地址加端口号,而UNIX Domain Socket的地址是一个socket类型的文件在文件系统中的路径,这个socket文件由bind()调用 创建,如果调用bind()时该文件已存在,则bind()错误返回。 #define UNIX_PATH_MAX 108 struct sockaddr_un { sa_family_tsun_family; /* AF_UNIX */ charsun_path[UNIX_PATH_MAX]; /* pathname */ }; 二、回射/客户服务器程序 通信的流程跟 前面说过的tcp/udp 是类似的,下面直接来看程序:
/*************************************************************************
> File Name: echoser_tcp.c
> Author: Simba
> Mail: dameng34@163.com
> Created Time: Sun 03 Mar 2013 06:13:55 PM CST
************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>
#include<sys/un.h>
#define ERR_EXIT(m)
do {
perror(m);
exit(EXIT_FAILURE);
} while (0)
void echo_ser(int conn)
{
char recvbuf[1024];
int n;
while (1)
{
memset(recvbuf, 0, sizeof(recvbuf));
n = read(conn, recvbuf, sizeof(recvbuf));
if (n == -1)
{
if (n == EINTR)
continue;
ERR_EXIT("read error");
}
else if (n == 0)
{
printf("client closen");
break;
}
fputs(recvbuf, stdout);
write(conn, recvbuf, strlen(recvbuf));
}
close(conn);
}
/* unix domain socket与TCP套接字相比较,在同一台主机的传输速度前者是后者的两倍。*/
int main(void)
{
int listenfd;
if ((listenfd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
ERR_EXIT("socket error");
unlink("/tmp/test socket"); //地址复用
struct sockaddr_un servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sun_family = AF_UNIX;
strcpy(servaddr.sun_path, "/tmp/test socket");
if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
ERR_EXIT("bind error");
if (listen(listenfd, SOMAXCONN) < 0)
ERR_EXIT("listen error");
int conn;
pid_t pid;
while (1)
{
conn = accept(listenfd, NULL, NULL);
if (conn == -1)
{
if (conn == EINTR)
continue;
ERR_EXIT("accept error");
}
pid = fork();
if (pid == -1)
ERR_EXIT("fork error");
if (pid == 0)
{
close(listenfd);
echo_ser(conn);
exit(EXIT_SUCCESS);
}
close(conn);
}
return 0;
}
(编辑:佛山站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |

