13.2 Linux_网络编程_UNIX域套接字

概述

什么是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;
}
相关推荐
小贾要学习19 小时前
【C++后端开发项目】Reactor 模型 / C++ 仿写 muduo HTTP 服务器:让底层网络库真正跑起网页
linux·服务器·c++·http·网络编程·muduo·reactor模型
Blockbuater_drug19 小时前
OpenMM分子动力学模拟02 安装:Linux:conda 一条命令装通 GPU 加速的分子模拟环境
linux·conda·cuda·gpu驱动·pythonpath·openmm安装
SDWAN_Cheap19 小时前
BGP是什么,广播IP是什么?两个容易混淆的概念拆解
网络·tcp/ip·bgp·广播ip
程序员JerrySUN19 小时前
PCIe Gen5 SSD 为什么读得快、写得慢?从存储原理到 Linux 性能实测
linux·服务器·网络
Android系统攻城狮19 小时前
Linux FFmpeg深度解析之avcodec_parameters_copy调用流程与实战(二十五)
linux·运维·服务器·ffmpeg·音视频·车载音频
guizhoumen19 小时前
net core下WebSocket请求总是断开的解决方案
网络·websocket·网络协议
HKT_China20 小时前
香港电讯河套区创新科技中心暨AI机楼揭幕,以网络基建助力北部都会区发展
网络·ai
云边云科技_云网融合20 小时前
案例分享 | 某运动零售品牌多云治理实战:一套框架解决权限失控、网络混乱与成本黑箱
网络·零售
ITKEY_20 小时前
emacs 文件管理Dired, the Directory Editor
linux·编辑器·emacs
源图客20 小时前
解决CentOS操作系统网络异常问题
linux·运维·centos