网络编程(33)—— 使用AF_UNIX构建本地通信的socket服务端和客户端

时间:2021-10-18 22:29:00
        之前一直使用AF_INET构造socket服务端和客户端,本文介绍下使用AF_UNIX构建本地通信的socket服务端和客户端。我们先列出代码,然后在对代码进行分析:

服务端:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/socket.h>
#include<string.h>
#include<sys/un.h>//头文件发生了变化
#define BUF_SIZE 1024

void error_handling(const char* message);
int main()
{
int serv_sock,clnt_sock;
//采用的地址结构体不再是sockaddr_in,而是sockaddr_un
struct sockaddr_un serv_addr,clnt_addr;
int clnt_addr_sz,str_len;
char buf[BUF_SIZE];
char * path="sock";
//创建socket时,协议族改为AF_UNIX
serv_sock=socket(AF_UNIX,SOCK_STREAM,0);
//填写的地址信息发生变化,没有了IP地址和端口号而是通过本地文件为媒介进行通信
serv_addr.sun_family=AF_UNIX;
strncpy(serv_addr.sun_path,path,strlen(path));

if(bind(serv_sock,(struct sockaddr*)&serv_addr,sizeof(serv_addr))==-1)
error_handling("bind() error");

if(listen(serv_sock,1)==-1)
error_handling("listen() error");

clnt_addr_sz=sizeof(clnt_addr);
if((clnt_sock=accept(serv_sock,(struct sockaddr*)&clnt_addr,&clnt_addr_sz))==-1)
error_handling("accept() error");

while(1)
{
str_len = read(clnt_sock,buf,BUF_SIZE);
if(str_len<=0)
break;
write(clnt_sock,buf,str_len);
}

close(clnt_sock);
close(serv_sock);
return 0;
}
void error_handling(const char* message)
{
fputs(message,stderr);
fputc('\n',stderr);
exit(1);
}

客户端:

#include<stdio.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/un.h>
#include<string.h>
#define BUF_SIZE 1024

int main()
{
int sock;
struct sockaddr_un addr;
int str_len;
char buf[BUF_SIZE];
char* path="sock";
sock=socket(AF_UNIX,SOCK_STREAM,0);

addr.sun_family=AF_UNIX;
strncpy(addr.sun_path,path,strlen(path));

connect(sock,(struct sockadd*)&addr,sizeof(addr));

while(1)
{
fputs("input:",stdout);
fgets(buf,BUF_SIZE,stdin);
if(!strcmp(buf,"q\n")||!strcmp(buf,"Q\n"))
break;
write(sock,buf,BUF_SIZE);
str_len=read(sock,buf,BUF_SIZE-1);
buf[str_len]=0;
printf("the message from serv:%s\n",buf);

}
close(sock);
return 0;
}

        以上是一个socket本地回声服务端和客户端的代码,从代码上也可以看出,是通过一个本地文件sock来实现和客户端进行通信的,本质上其实就是进程间的通信,和之前网络通信的服务端相比,主要有以下改动:
1、创建的socket协议族不同,创建网络通信的socket时我们用的AF_INET,而创建本地通信的socket时用的协议族是AF_UNIX。
2、使用的地址不同,主要表现在:
(1)头文件不同,本地通信使用的是sys/un.h头文件
(2)地址结构体不同,本地通信使用struct sockaddr_un
(3)地址的赋值不同,分别使用struct sockaddr_un的sun_family成员存储协议族信息,sun_path成员存储用于通信的中间文件。
        其实除了以上节点和网络通信的区别之外,其他基本相同。
        另外需要注意的是,进行本地通信时,我们定义了一个本地通信的中间文件sock,但是实际上每次连接,程序都会通过将sock重命名的方式生成另外的文件,也就是说每次连接的中间文件都会不同,请看下图中,红色圈出部分,我进行了三次连接,就出现了三个以sock开头的文件。

网络编程(33)—— 使用AF_UNIX构建本地通信的socket服务端和客户端


Github位置:
https://github.com/HymanLiuTS/NetDevelopment
克隆本项目:
Git clone git@github.com:HymanLiuTS/NetDevelopment.git
获取本文源代码:
git checkout NL33