Unix domain socket 又叫 IPC(inter-process communication 进程间通信) socket,用于实现同一主机上的进程间通信。socket 原本是为网络通讯设计的,但后来在 socket 的框架上发展出一种 IPC 机制,就是 UNIX domain socket。虽然网络 socket 也可用于同一台主机的进程间通讯(通过 loopback 地址 127.0.0.1),但是 UNIX domain socket 用于 IPC 更有效率:不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程。这是因为,IPC 机制本质上是可靠的通讯,而网络协议是为不可靠的通讯设计的。
#include <.h>
<span style="color: #0000ff">#define MAXLINE 80
<span style="color: #0000ff">char *socket_path = <span style="color: #800000">"<span style="color: #800000">server.socket<span style="color: #800000">"<span style="color: #000000">;
<span style="color: #0000ff">int main(<span style="color: #0000ff">void<span style="color: #000000">)
{
<span style="color: #0000ff">struct<span style="color: #000000"> sockaddr_un serun,cliun;
socklen_t cliun_len;
<span style="color: #0000ff">int<span style="color: #000000"> listenfd,connfd,size;
<span style="color: #0000ff">char<span style="color: #000000"> buf[MAXLINE];
<span style="color: #0000ff">int<span style="color: #000000"> i,n;
</span><span style="color: #0000ff">if</span> ((listenfd = socket(AF_UNIX,SOCK_STREAM,<span style="color: #800080">0</span>)) < <span style="color: #800080">0</span><span style="color: #000000">) {
perror(</span><span style="color: #800000">"</span><span style="color: #800000">socket error</span><span style="color: #800000">"</span><span style="color: #000000">);
exit(</span><span style="color: #800080">1</span><span style="color: #000000">);
}
memset(</span>&serun,<span style="color: #800080">0</span>,<span style="color: #0000ff">sizeof</span><span style="color: #000000">(serun));
serun.sun_family </span>=<span style="color: #000000"> AF_UNIX;
strcpy(serun.sun_path,socket_path);
size </span>= offsetof(<span style="color: #0000ff">struct</span> sockaddr_un,sun_path) +<span style="color: #000000"> strlen(serun.sun_path);
unlink(socket_path);
</span><span style="color: #0000ff">if</span> (bind(listenfd,(<span style="color: #0000ff">struct</span> sockaddr *)&serun,size) < <span style="color: #800080">0</span><span style="color: #000000">) {
perror(</span><span style="color: #800000">"</span><span style="color: #800000">bind error</span><span style="color: #800000">"</span><span style="color: #000000">);
exit(</span><span style="color: #800080">1</span><span style="color: #000000">);
}
printf(</span><span style="color: #800000">"</span><span style="color: #800000">UNIX domain socket boundn</span><span style="color: #800000">"</span><span style="color: #000000">);
</span><span style="color: #0000ff">if</span> (listen(listenfd,<span style="color: #800080">20</span>) < <span style="color: #800080">0</span><span style="color: #000000">) {
perror(</span><span style="color: #800000">"</span><span style="color: #800000">listen error</span><span style="color: #800000">"</span><span style="color: #000000">);
exit(</span><span style="color: #800080">1</span><span style="color: #000000">);
}
printf(</span><span style="color: #800000">"</span><span style="color: #800000">Accepting connections ...n</span><span style="color: #800000">"</span><span style="color: #000000">);
</span><span style="color: #0000ff">while</span>(<span style="color: #800080">1</span><span style="color: #000000">) {
cliun_len </span>= <span style="color: #0000ff">sizeof</span><span style="color: #000000">(cliun);
</span><span style="color: #0000ff">if</span> ((connfd = accept(listenfd,(<span style="color: #0000ff">struct</span> sockaddr *)&cliun,&cliun_len)) < <span style="color: #800080">0</span><span style="color: #000000">){
perror(</span><span style="color: #800000">"</span><span style="color: #800000">accept error</span><span style="color: #800000">"</span><span style="color: #000000">);
</span><span style="color: #0000ff">continue</span><span style="color: #000000">;
}
</span><span style="color: #0000ff">while</span>(<span style="color: #800080">1</span><span style="color: #000000">) {
n </span>= read(connfd,buf,<span style="color: #0000ff">sizeof</span><span style="color: #000000">(buf));
</span><span style="color: #0000ff">if</span> (n < <span style="color: #800080">0</span><span style="color: #000000">) {
perror(</span><span style="color: #800000">"</span><span style="color: #800000">read error</span><span style="color: #800000">"</span><span style="color: #000000">);
</span><span style="color: #0000ff">break</span><span style="color: #000000">;
} </span><span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span>(n == <span style="color: #800080">0</span><span style="color: #000000">) {
printf(</span><span style="color: #800000">"</span><span style="color: #800000">EOFn</span><span style="color: #800000">"</span><span style="color: #000000">);
</span><span style="color: #0000ff">break</span><span style="color: #000000">;
}
printf(</span><span style="color: #800000">"</span><span style="color: #800000">received: %s</span><span style="color: #800000">"</span><span style="color: #000000">,buf);
</span><span style="color: #0000ff">for</span>(i = <span style="color: #800080">0</span>; i < n; i++<span style="color: #000000">) {
buf[i] </span>=<span style="color: #000000"> toupper(buf[i]);
}
write(connfd,n);
}
close(connfd);
}
close(listenfd);
</span><span style="color: #0000ff">return</span> <span style="color: #800080">0</span><span style="color: #000000">;
}
socket( family, type, protocol);
family 指定为 AF_UNIX,使用 AF_UNIX 会在系统上创建一个 socket 文件,不同进程通过读写这个文件来实现通信。type 可以选择 SOCK_DGRAM 或 SOCK_STREAM。SOCK_STREAM 意味着会提供按顺序的、可靠、双向、面向连接的比特流。SOCK_DGRAM 意味着会提供定长的、不可靠、无连接的通信。protocol 参数指定为 0 即可。
#include <.h>
<span style="color: #0000ff">#define MAXLINE 80
<span style="color: #0000ff">char client_path = <span style="color: #800000">"<span style="color: #800000">client.socket<span style="color: #800000">"<span style="color: #000000">;
<span style="color: #0000ff">char server_path = <span style="color: #800000">"<span style="color: #800000">server.socket<span style="color: #800000">"<span style="color: #000000">;
<span style="color: #0000ff">int<span style="color: #000000"> main() {
<span style="color: #0000ff">struct<span style="color: #000000"> sockaddr_un cliun,serun;
<span style="color: #0000ff">int<span style="color: #000000"> len;
<span style="color: #0000ff">char buf[<span style="color: #800080">100<span style="color: #000000">];
<span style="color: #0000ff">int<span style="color: #000000"> sockfd,n;
</span><span style="color: #0000ff">if</span> ((sockfd = socket(AF_UNIX,<span style="color: #800080">0</span>)) < <span style="color: #800080">0</span><span style="color: #000000">){
perror(</span><span style="color: #800000">"</span><span style="color: #800000">client socket error</span><span style="color: #800000">"</span><span style="color: #000000">);
exit(</span><span style="color: #800080">1</span><span style="color: #000000">);
}
</span><span style="color: #008000">//</span><span style="color: #008000"> 一般显式调用bind函数,以便服务器区分不同客户端 </span>
memset(&cliun,<span style="color: #0000ff">sizeof</span><span style="color: #000000">(cliun));
cliun.sun_family </span>=<span style="color: #000000"> AF_UNIX;
strcpy(cliun.sun_path,client_path);
len </span>= offsetof(<span style="color: #0000ff">struct</span> sockaddr_un,sun_path) +<span style="color: #000000"> strlen(cliun.sun_path);
unlink(cliun.sun_path);
</span><span style="color: #0000ff">if</span> (bind(sockfd,len) < <span style="color: #800080">0</span><span style="color: #000000">) {
perror(</span><span style="color: #800000">"</span><span style="color: #800000">bind error</span><span style="color: #800000">"</span><span style="color: #000000">);
exit(</span><span style="color: #800080">1</span><span style="color: #000000">);
}
memset(</span>&serun,server_path);
len </span>= offsetof(<span style="color: #0000ff">struct</span> sockaddr_un,sun_path) +<span style="color: #000000"> strlen(serun.sun_path);
</span><span style="color: #0000ff">if</span> (connect(sockfd,len) < <span style="color: #800080">0</span><span style="color: #000000">){
perror(</span><span style="color: #800000">"</span><span style="color: #800000">connect error</span><span style="color: #800000">"</span><span style="color: #000000">);
exit(</span><span style="color: #800080">1</span><span style="color: #000000">);
}
</span><span style="color: #0000ff">while</span>(fgets(buf,MAXLINE,stdin) !=<span style="color: #000000"> NULL) {
write(sockfd,strlen(buf));
n </span>=<span style="color: #000000"> read(sockfd,MAXLINE);
</span><span style="color: #0000ff">if</span> ( n < <span style="color: #800080">0</span><span style="color: #000000"> ) {
printf(</span><span style="color: #800000">"</span><span style="color: #800000">the other side has been closed.n</span><span style="color: #800000">"</span><span style="color: #000000">);
}</span><span style="color: #0000ff">else</span><span style="color: #000000"> {
write(STDOUT_FILENO,n);
}
}
close(sockfd);
</span><span style="color: #0000ff">return</span> <span style="color: #800080">0</span><span style="color: #000000">;
}
$ server.c - client.c -o client


(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|