首页 > 编程语言 >【网络编程开发】10.UNIX套接字域

【网络编程开发】10.UNIX套接字域

时间:2024-06-10 15:31:46浏览次数:30  
标签:10 addr sockaddr UNIX peer 接字 include

10.UNIX套接字域

UNIX域套接字是用于在同一台计算机上运行的进程之间进行通信的一种机制。它与传统基于TCP/IP协议栈的套接字不同,UNIX域套接字操作更为高效,因为它避免了网络层的开销,不涉及网络报头、检验和、顺序号等复杂的网络协议处理过程。UNIX域套接字的特点包括:

  1. 高效的本地通信:由于不需要网络层面的处理,UNIX域套接字在本地进程间通信时比使用TCP套接字更高效。
  2. 路径名作为地址:UNIX域套接字使用文件系统中的路径名作为地址,创建套接字时会在文件系统相应位置创建一个类型为套接字的文件。
  3. 两种类型的套接字:UNIX域套接字提供流式(SOCK_STREAM)和数据包式(SOCK_DGRAM)两种类型的套接字,且都是可靠的。
  4. 权限问题:绑定UNIX域套接字时,调用进程需要有对应目录部分的可写权限,并且默认情况下,创建的文件具有777的权限。
  5. 抽象路径名:Linux特有的特性,允许将UNIX域套接字绑定到一个名字上,而不会实际在文件系统中创建文件。
  6. 传递文件描述符:UNIX域套接字可以在同一台主机上的各进程之间传递文件描述符。
  7. 编程接口:虽然API调用方式与TCP/IP套接字类似,但在UNIX域套接字中,地址是以sockaddr_un结构体来表示的。

流式和数据包式的区别

特性流式 SOCK_STREAM数据包式 SOCK_DGRAM
连接方式面向连接(TCP协议)无连接(UDP协议)
可靠性高(错误检测和重传机制)低(无错误检测和重传)
数据传输方式字节流(可能分段)数据报文(独立单位)
资源消耗较大(维护连接状态)较小(无需维护连接)
处理速度较慢(保证可靠性)较快(不保证可靠性)
适用场景文件传输、远程登录等音视频传输、广播消息等
网络环境适应性适用于稳定网络环境适用于局域网或实时性要求高的环境

UNIX流式套接字

示例代码

在Linux终端输入命令:man bind 滑到下面查看示例代码

在这里插入图片描述

复制示例代码并稍作修改

服务端

UNIX_sever.c

#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define MY_SOCK_PATH "/tmp/my_sock_file" // 套接字文件地址
#define LISTEN_BACKLOG 50 // 监听队列长度

#define handle_error(msg) \n	do { perror(msg); exit(EXIT_FAILURE); } while (0) // 错误处理宏

int main(int argc, char *argv[])
{
	int sfd, cfd; // 服务器套接字描述符和客户端套接字描述符
	struct sockaddr_un my_addr, peer_addr; // 地址结构体
	socklen_t peer_addr_size; // 客户端地址结构体大小
	char buf[BUFSIZ] = {}; // 缓冲区

	sfd = socket(AF_UNIX, SOCK_STREAM, 0); // 创建套接字
	if (sfd == -1)
		handle_error("socket"); // 错误处理

	memset(&my_addr, 0, sizeof(struct sockaddr_un)); // 清空地址结构体
	my_addr.sun_family = AF_UNIX; // 设置地址类型为AF_UNIX
	strncpy(my_addr.sun_path, MY_SOCK_PATH, sizeof(my_addr.sun_path) - 1); // 设置套接字文件路径

	if (bind(sfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr_un)) == -1) // 绑定套接字
		handle_error("bind"); // 错误处理

	if (listen(sfd, LISTEN_BACKLOG) == -1) // 监听套接字
		handle_error("listen"); // 错误处理

	peer_addr_size = sizeof(struct sockaddr_un); // 获取客户端地址结构体大小
	cfd = accept(sfd, (struct sockaddr *) &peer_addr, &peer_addr_size); // 接受客户端连接
	if (cfd == -1)
		handle_error("accept"); // 错误处理

	recv(cfd, buf, BUFSIZ, 0); // 接收客户端发送的数据
	printf("buf = %s\n", buf); // 打印接收到的数据

	close(cfd); // 关闭客户端套接字
	close(sfd); // 关闭服务器套接字

	return 0;
}
  1. 编译:gcc -o UNIX_sever UNIX_sever.c -Wall
  2. 运行:./UNIX_sever
  3. 结束运行:ctrl+c
  4. 再次运行:./UNIX_sever报错,bind: Address already in use

在这里插入图片描述

  1. 删除套接字文件:rm /tmp/my_sock_file
  2. 再次运行:./UNIX_sever,报错消失
  3. 原因:ctrl+c 强制结束没有执行remove(MY_SOCK_PATH); 所以要手动删除

客户端

#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define MY_SOCK_PATH "/tmp/my_sock_file"//套接字文件地址

#define handle_error(msg) \n	do { perror(msg); exit(EXIT_FAILURE); } while (0)

int main(int argc, char *argv[])
{
	int fd; // 文件描述符
	struct sockaddr_un peer_addr; // UNIX域套接字地址结构体
	char buf[BUFSIZ] = {"Hello World"}; // 发送缓冲区

	fd = socket(AF_UNIX, SOCK_STREAM, 0); // 创建套接字
	if (fd == -1)
		handle_error("socket"); // 错误处理

	memset(&peer_addr, 0, sizeof(struct sockaddr_un)); // 清空地址结构体
	peer_addr.sun_family = AF_UNIX; // 设置地址类型为AF_UNIX
	strncpy(peer_addr.sun_path, MY_SOCK_PATH, sizeof(peer_addr.sun_path) - 1); // 设置套接字文件路径

	if (connect(fd, (struct sockaddr *) &peer_addr, sizeof(struct sockaddr_un)) == -1) // 连接服务器
		handle_error("connect"); // 错误处理

	send(fd, buf, strlen(buf), 0); // 发送数据

	close(fd); // 关闭套接字
	remove(MY_SOCK_PATH); // 删除套接字文件
	return 0;
}

在这里插入图片描述

UNIX数据包式套接字

服务端

#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define MY_SOCK_PATH "/tmp/my_sock_file"
#define handle_error(msg) \n	do { perror(msg); exit(EXIT_FAILURE); } while (0)

int main(int argc, char *argv[])
{
	int fd;
	struct sockaddr_un my_addr, peer_addr;
	socklen_t peer_addr_size;
	char buf[BUFSIZ] = {};

	// 创建UDP套接字
	fd = socket(AF_UNIX, SOCK_DGRAM, 0);
	if (fd == -1)
		handle_error("socket");

	// 清空地址结构体并设置类型和路径
	memset(&my_addr, 0, sizeof(struct sockaddr_un));
	my_addr.sun_family = AF_UNIX;
	strncpy(my_addr.sun_path, MY_SOCK_PATH,
			sizeof(my_addr.sun_path) - 1);

	// 绑定套接字到指定路径
	if (bind(fd, (struct sockaddr *) &my_addr,
				sizeof(struct sockaddr_un)) == -1)
		handle_error("bind");

	// 接收数据并打印
	peer_addr_size = sizeof(struct sockaddr_un);
	recvfrom(fd, buf, BUFSIZ, 0, (struct sockaddr *) &peer_addr,&peer_addr_size);
	printf("%s\n",buf);

	// 关闭套接字并删除文件
	close(fd);
	remove(MY_SOCK_PATH);
	return 0;
}

客户端

#include <sys/socket.h> 
#include <sys/un.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 

#define MY_SOCK_PATH "/tmp/my_sock_file" // 定义套接字文件路径
#define handle_error(msg) \n	do { perror(msg); exit(EXIT_FAILURE); } while (0) // 定义错误处理宏

int main(int argc, char *argv[]) 
{
	int fd; // 文件描述符
	struct sockaddr_un peer_addr; // UNIX域套接字地址结构体
	socklen_t peer_addr_size; // UNIX域套接字地址大小
	char buf[BUFSIZ] = {"Hello World!"}; // 发送缓冲区

	fd = socket(AF_UNIX, SOCK_DGRAM, 0); // 创建UDP套接字
	if (fd == -1)
		handle_error("socket"); 

	memset(&peer_addr, 0, sizeof(struct sockaddr_un)); // 清空地址结构体
	peer_addr.sun_family = AF_UNIX; // 设置地址类型为AF_UNIX
	strncpy(peer_addr.sun_path, MY_SOCK_PATH,
			sizeof(peer_addr.sun_path) - 1); // 设置套接字文件路径

	peer_addr_size = sizeof(struct sockaddr_un); // 获取地址大小
	printf("%s\n", buf); // 打印发送缓冲区内容
	sendto(fd, buf, strlen(buf), 0, (struct sockaddr *) &peer_addr,peer_addr_size); // 向服务器发送数据
	close(fd); // 关闭套接字
	remove(MY_SOCK_PATH); // 删除套接字文件
	return 0; 
}

在这里插入图片描述

通信成功

标签:10,addr,sockaddr,UNIX,peer,接字,include
From: https://blog.csdn.net/2201_75563094/article/details/139558768

相关文章

  • 科学使用Typora 1.8.10.0,2024新版,保姆级手把手教程,破解困扰
    写一篇如何在此版本解除付费的文章,希望能帮助更多跟我一样的学生党或者有需要的人,有能力的各位还是希望大家尊重一下知识付费。非常简单,大家跟着一步步做就行了。下载Typora官网链接:Typora官方中文站(typoraio.cn)首先是安装后的激活到Typora\resources\page-dist\stati......
  • 2024-6-10 石群电路-28
    2024-6-10,星期一,14:15,天气:晴,心情:晴。今天又是阳光明媚的一天,自从减肥成功and道家养生后,越来越感觉夏热冬冷,夏长冬藏这一自然规律了,虽然外面艳阳高照的,但是确实不吹空调,不吃冰棍,自然而然出出汗,洗洗澡,吃吃西瓜真的很舒服,空调的冯确实不是什么好风,希望大家都身体健康,快快乐乐的,端......
  • 动手学深度学习4.10 实战Kaggle比赛:预测房价-笔记&练习(PyTorch)
    以下内容为结合李沐老师的课程和教材补充的学习笔记,以及对课后练习的一些思考,自留回顾,也供同学之人交流参考。本节课程地址:实战Kaggle比赛:预测房价_哔哩哔哩_bilibili本节教材地址:4.10.实战Kaggle比赛:预测房价—动手学深度学习2.0.0documentation(d2l.ai)本节开源代......
  • C++Primer Plus 第12章 类和动态内存分配 12.10编程练习第2题new,delete的指向深度拷
    系列文章目录提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加例如:本章练习第2题涉及标准函数及关键词toupper,tolower(),strcpy_s(),strcat_s(),strcmp,strlen(),new[],delete[].实现如下效果输出应与下面相似:Pleaseenteryourname:FrettaFarboMynameis......
  • web入门(1)---6.10
    总结:多做一点NSSCTF的新手赛,了解基本题型,然后打牢基础知识谢队讲解攻防世界Web入门题讲解_哔哩哔哩_bilibili题目来源:攻防世界新手区1.view_source查看源代码2.get_post收获:get方法是直接在url网址后面?a=1这样发送请求post是点击postdate3.robots收获:ro......
  • 力扣每日一题 6/10
    881.救生艇[中等]题目:给定数组 people 。people[i]表示第 i 个人的体重 ,船的数量不限,每艘船可以承载的最大重量为 limit。每艘船最多可同时载两人,但条件是这些人的重量之和最多为 limit。返回 承载所有人所需的最小船数 。示例1:输入:people=[1,2],limit=......
  • 202400610刷题总结
    T1T559。T2(带权并查集)1380。把行和列的取值看成变量,其中行取1代表+1,列取1代表-1,为了凑x-y=c,这样可以拿并查集来做了。维护d[x],到根的距离,我们把边定义为+,反向走为-。这样就行了,如果在一个集合,那么判断距离是不是c。还可以差分约束,dfs(直接遍历一遍,遇到环就判断).#i......
  • 【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 机场航班调度程序(100分) - 三语言A
    ......
  • 信息学奥赛一本通第1022题
    1022:整型与布尔型的转换【题目描述】将一个整型变量的值赋给一个布尔型变量,再将这个布尔型变量的值赋给一个整型变量,得到的值是多少?【输入】一个整型范围内的整数,即初始时整型变量的值。【输出】一个整数,经过上述过程后得到的结果。【输入样例】3【输出样例】1......
  • Tektronix 泰克 MDO4104C 混合域示波器
    Tektronix泰克MDO4104C混合域示波器主要性能指标1.示波器4 条模拟通道1 GHz、500 MHz、350 MHz和200 MHz带宽型号带宽可升级(最高达1 GHz)最高达5 GS/s采样率所有通道上20 M记录长度>340,000 wfm/s的最大波形捕获速率标配无源电压探头,3.9 pF电容负载,1......