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

news2025/1/15 20:55:05

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; 
}

在这里插入图片描述

通信成功

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1804896.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

系统架构设计师重难点知识脑图

大家都知道现在的软考自从变成机考后,越来越难了,教程上的内容不仅全还细,几乎任何内容都有可能考,出题老师主打一个出其不意,比如2024年5月考试,连UML时序图的片段都考,这 种如果看书的话一般都是一瞟而过,而实际工作中又很少会这么严格的去画片段。 所以对于教程上的…

VB7/64位VB6开发工具office插件开发-twinbasic

全新的VB7&#xff0c;twinbasic&#xff0c;支持64位开发&#xff0c;支持EXCEL插件开发&#xff0c;老外连续3年闭关修练终成正果 官方最新版下载&#xff1a;https://github.com/twinbasic/twinbasic/releases 汉化工具用法&#xff1a;把工具和Lang_Tool目录复制到Twinbasi…

C#操作MySQL从入门到精通(15)——分组数据

前言 我们有时候需要对数据库中查询的数据进行分组,所谓分组就是将相同的数据分为一组,本次测试使用的数据库数据如下: 1、分组 分组使用group by关键词,下面的代码的意思是对查询的结果按照student_age进行分组,student_age相同的划分为同一组 string sql = string.E…

C#操作MySQL从入门到精通(16)——使用子查询

前言: 我们在查询数据的过程中有时候查询的数据不是从数据库中来的,而是从另一个查询的结果来的,这时候就需要使用子查询,本文使用的测试数据如下: 1、子查询 下面的代码就是先查询地址是安徽和广西的学生年龄,然后获取年龄对应的姓名 private void button__SubQuery…

windows环境安装多版本jdk与环境切换

1&#xff1a;JDK官网下载 2&#xff1a;安装目录 3&#xff1a;在系统环境变量新添加JAVA_HOME_8和JAVA_HOME_21 4&#xff1a;设置默认使用jdk21&#xff0c;如果需要切换&#xff0c;就更改JAVA_HOME的变量值 5&#xff1a;在环境变量path添加&#xff0c;%JAVA_HOME%\bin和…

10 -每台机器的进程平均运行时间(高频 SQL 50 题基础版)

10 - 每台机器的进程平均运行时间 -- sum(if(activity_type end,timestamp ,-timestamp )) -- 如果activity_type为“end”,值为timestamp&#xff0c;为“start” 为-timestamp&#xff0c;所有数相加end-start -- count(distinct process_id),获取同一机器有几个进行id -- r…

【MYSQL系列】mysql中text,longtext,mediumtext区别

【MYSQL系列】mysql中text,longtext,mediumtext区别 在MySQL数据库中&#xff0c;TEXT、LONGTEXT和MEDIUMTEXT都是用于存储大量文本数据的字段类型。它们之间的主要区别在于可存储的数据大小和性能方面的差异。本文将探讨这些字段类型的特点、使用场景和一些最佳实践。 TEXT类…

PDF分页处理:技术与实践

引言 在数字化办公和学习中&#xff0c;PDF文件因其便携性和格式稳定性而广受欢迎。然而&#xff0c;处理大型PDF文件时&#xff0c;我们经常需要将其拆分成单独的页面&#xff0c;以便于管理和分享。本文将探讨如何使用Python编程语言和一些流行的库来实现PDF文件的分页处理。…

Langchain 新玩法:LangGraph 赋能 RAG Agent,自适应、自校正、Self-RAG

节前&#xff0c;我们组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、今年参加社招和校招面试的同学。 针对大模型技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备面试攻略、面试常考点等热门话题进行了深入的讨论。 汇总合集…

【讯为Linux驱动开发】5.并发与竞争

并发&#xff1a;一个CPU在一个时间片只能执行一个任务&#xff0c;切换速度很快。 并行&#xff1a;双核CPU&#xff0c;真正的同时执行两个任务 并行就是并发的理想情况&#xff0c;统称并发。 【问】Linux在什么情况下产生并发&#xff1f; 1.中断中修改公共资源 2.抢占…

【UML用户指南】-11-对高级结构建模-高级关系

目录 1、依赖&#xff08;dependency&#xff09; 1.1.1、绑定&#xff08;bind&#xff09; 1.1.2、导出&#xff08;derive&#xff09; 1.1.3、允许&#xff08;permit&#xff09; 1.1.4、实例&#xff08;instanceOf&#xff09; 1.1.5、实例化&#xff08;instanti…

【PL理论】(11) F#:标准库之 Set | 标准库之 Map

&#x1f4ad; 写在前面&#xff1a;本章我们将简要的介绍一下 Set 和 Map &#xff08;非常简要&#xff0c;简要至极&#xff09; 目录 0x00 标准库之集合&#xff08;Set&#xff09; 0x01 标准库之 Map 0x00 标准库之集合&#xff08;Set&#xff09; 集合中的元素具有…

【调整堆】(C++ 代码实现 注释详解)

自定义结构体&#xff1a; #define sz 105 typedef struct node{int length;int l[sz]; }SqList; 调整堆的函数&#xff1a; HeapAdjust函数思路说明&#xff1a; //目标&#xff1a;将以s为根的子树调整为大根堆 //具体操作&#xff1a;将路径上比s大的都往上移动,s往下移…

屏幕空间反射技术在AI绘画中的作用

在数字艺术和游戏开发的世界中&#xff0c;真实感渲染一直是追求的圣杯。屏幕空间反射&#xff08;Screen Space Reflection&#xff0c;SSR&#xff09;技术作为一种先进的图形处理手段&#xff0c;它通过在屏幕空间内模拟光线的反射来增强场景的真实感和视觉冲击力。随着人工…

selenium-java自动化教程

文章目录 Selenium支持语言WebDriver 开始使用chromedriver模拟用户浏览访问模拟点击事件关闭弹窗&#xff0c;选中元素并点击 获取页面文本结语 Selenium Selenium是一个自动化测试工具&#xff0c;可以模拟用户操作web端浏览器的行为&#xff0c;包括点击、输入、选择等。也可…

第十一届蓝桥杯C++青少年组中/高级组省赛2020年真题解析

一、单选题 第1题 表达式 ‘6’ - ‘1’ 的值是( ) A:整数 5 B:字符 5 C:表达式不合法 D:字符 6 答案&#xff1a;A 在 C 中&#xff0c;字符字面量用单引号括起来&#xff0c;例如 ‘6’ 和 ‘1’。这些字符字面量实际上是表示字符的 ASCII 值。在 ASCII 编码中&#xff0…

【机器学习】消息传递神经网络(MPNN)在分子预测领域的医学应用

1. 引言 1.1. 分子性质预测概述 分子性质预测是计算机辅助药物发现流程中至关重要的任务之一&#xff0c;它在许多下游应用如药物筛选和药物设计中发挥着核心作用&#xff1a; 1.1.1. 目的与重要性&#xff1a; 分子性质预测旨在通过分子内部信息&#xff08;如原子坐标、原…

2.数人数

上海市计算机学会竞赛平台 | YACSYACS 是由上海市计算机学会于2019年发起的活动,旨在激发青少年对学习人工智能与算法设计的热情与兴趣,提升青少年科学素养,引导青少年投身创新发现和科研实践活动。https://www.iai.sh.cn/problem/431 题目描述 在一个班级里,男生比女生多…

MySQL—多表查询—子查询(介绍)

一、引言 上一篇博客学习完联合查询。 这篇开始&#xff0c;就来到多表查询的最后一种形式语法块——子查询。 &#xff08;1&#xff09;概念 SQL 语句中嵌套 SELECT 语句&#xff0c;那么内部的 select 称为嵌套查询&#xff0c;又称子查询。 表现形式 注意&#xff1a; …

达梦8 开启物理逻辑日志对系统的影响

物理逻辑日志&#xff0c;是按照特定的格式存储的服务器的逻辑操作&#xff0c;专门用于 DBMS_LOGMNR 包挖掘获取数据库系统的历史执行语句。当开启记录物理逻辑日志的功能时&#xff0c;这部分日志内 容会被存储在重做日志文件中。 要开启物理逻辑日志的功能&#xff0c;需要…