概述
什么是UNIX域套接字:
UNIX域套接字是使用套接字进行本地通信,TCP/UDP是使用套接字进行网络通信。UNIX域套接字也有域流式套接字和域数据报套接字,这两种形式域TCP/UDP的含义类似,使用步骤也完全一致。
bind时绑定的结构体类型:
cpp
struct sockaddr_un {
sa_family_t sun_family; //协议类型
char sun_path[104]; //套接字文件路径
};
域流式套接字
域流式套接字的创建步骤与TCP创建步骤一致。
server.c代码:
cpp
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <signal.h>
#include <sys/wait.h>
#define UNIX_PATH "./UNIX"
void Set_SIGCHLD(void);
void SIGCHLD_Handler(int sig);
int main(int argc ,char** argv){
int fd;
struct sockaddr_un addr;
//判断参数有效性
if(argc != 2){
printf("param err\n");
printf("%s<unix path>\n",argv[0]);
return -1;
}
printf("unix path = %s\n",argv[1]);
//1.创建socket
if((fd=socket(AF_UNIX,SOCK_STREAM,0))<0){//流式UNIX
perror("socket");
return -1;
}
//2.绑定
addr.sun_family = AF_UNIX; //UNIX
strncpy(addr.sun_path,argv[1],sizeof(addr.sun_path)); //UNIX文件路径
if(bind(fd,(struct sockaddr*)&addr,sizeof(struct sockaddr_un)) == -1){
perror("bind");
return -1;
}
//3.监听socket
if(listen(fd,5) == -1){ //允许最多接入5个客户端
perror("listen");
return -1;
}
//多进程并发
pid_t pid;
int newFd;
struct sockaddr_un newAddr;
socklen_t newAddrlen;
Set_SIGCHLD();//以信号方式回收子进程
while(1){
//4.接受客户端链接
if((newFd = accept(fd,(struct sockaddr*)&newAddr,&newAddrlen)) < 0){
perror("accept");
return -1;
}
//父进程处理接收客户端链接的问题
//子进程处理与客户端交互的问题
if((pid=fork()) == -1){
perror("fork");
return -1;
}
else if(pid == 0){
char buf[100] = {0};
close(fd);//对于子进程,socket返回的fd没有用
//5.数据交互
while(1){
memset(buf,0,sizeof(buf));
write(newFd,"server",strlen("server\n"));
read(newFd,buf,sizeof(buf)-1);
printf("read:%s\n",buf);
sleep(1);
}
exit(0);
}else{
close(newFd);//对于父进程,accept返回的newFd没有用
}
}
remove(argv[1]);
close(fd);
return 0;
}
void Set_SIGCHLD(void){
struct sigaction act;
act.sa_handler = SIGCHLD_Handler;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART;//让因为信号而终止的系统调用继续运行
if(sigaction(SIGCHLD,&act,NULL) != 0){
perror("sigaction");
}
}
void SIGCHLD_Handler(int sig){
int wstatus;
waitpid(-1,&wstatus,WNOHANG);
if(WIFEXITED(wstatus)){ //判断子进程是否正常退出
printf("子进程的返回值为%d\n",WEXITSTATUS(wstatus));
}else{
printf("子进程是否被信号结束%d\n",WIFSIGNALED(wstatus));
printf("结束子进程的信号类型%d\n",WTERMSIG(wstatus));
}
}
client.c代码 :
cpp
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/socket.h>
int main(int argc,char** argv){
int fd;
struct sockaddr_un addr;
//判断参数有效性
if(argc != 2){
printf("param err\n");
printf("%s<unix path>\n",argv[0]);
return -1;
}
printf("unix path = %s\n",argv[1]);
//1.创建socket
if((fd=socket(AF_UNIX,SOCK_STREAM,0))<0){//流式UNIX
perror("socket");
return -1;
}
//2.链接服务器
addr.sun_family = AF_UNIX; //UNIX
strncpy(addr.sun_path,argv[1],sizeof(addr.sun_path)); //UNIX文件路径
if(connect(fd,(struct sockaddr*)&addr,sizeof(struct sockaddr_un)) == -1){
perror("connect");
return -1;
}
//3.数据交互
char buf[100] = {0};
while(1){
if(read(fd,buf,sizeof(buf)-1) > 0){
printf("read:%s\n",buf);
write(fd,"client:i read it\n",strlen("client:i read it\n"));
}
}
close(fd);
return 0;
}
域数据报套接字
server.c
cpp
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/socket.h>
int main(int argc,char** argv){
int fd;
struct sockaddr_un addr;
//判断参数有效性
if(argc != 2){
printf("param err\n");
printf("%s<unix path>\n",argv[0]);
return -1;
}
printf("unix path = %s\n",argv[1]);
//1.创建socket
if((fd=socket(AF_UNIX,SOCK_DGRAM,0))<0){//数据报UNIX
perror("socket");
return -1;
}
//2.绑定IP、端口号
addr.sun_family = AF_UNIX; //UNIX
strncpy(addr.sun_path,argv[1],sizeof(addr.sun_path)); //UNIX文件路径
if(bind(fd,(struct sockaddr*)&addr,sizeof(struct sockaddr_un)) == -1){
perror("bind");
return -1;
}
//3.数据交互
char buf[100] = {0};
struct sockaddr_un src_addr;
socklen_t src_addrlen;
while(1){
memset(buf,0,sizeof(buf));
if(recvfrom(fd,buf,sizeof(buf)-1,0,(struct sockaddr*)&src_addr,&src_addrlen) > 0){
printf("read:%s\n",buf);
}
}
close(fd);
return 0;
}
client.c
cpp
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/socket.h>
int main(int argc,char** argv){
int fd;
struct sockaddr_un addr;
//判断参数有效性
if(argc != 2){
printf("param err\n");
printf("%s<unix path>\n",argv[0]);
return -1;
}
printf("unix path = %s\n",argv[1]);
//1.创建socket
if((fd=socket(AF_UNIX,SOCK_DGRAM,0))<0){//数据报UNIX
perror("socket");
return -1;
}
//2.设置要发送到的服务器信息
addr.sun_family = AF_UNIX; //UNIX
strncpy(addr.sun_path,argv[1],sizeof(addr.sun_path)); //UNIX文件路径
//3.数据交互
while(1){
sendto(fd,"cilent",strlen("cilent"),0,(struct sockaddr*)&addr,sizeof(addr));
sleep(1);
}
close(fd);
return 0;
}