AF_UNIX和127.0.0.1(AF_INET)回环地址写数据速度对比

在linux下,存在着这样的情况,本地的进程间通信,并且其中一个是服务端,另外的都是客户端。
服务端通过绑定端口,客户端往127.0.0.1的对应端口发送,即可办到,不过这样会浪费一个端口,同时也容易造成安全隐患。

今天发现linux服务端创建socket的时候,协议族用AF_UNIX即可,AF_LOCAL和AF_UNIX的值是一样的。

而AF_UNIX和127.0.0.1回环地址相比,具有哪些好处呢。本人读了下面博客:
Unix domain socket 简介

其中里面讲到UNIX domain socket 用于 IPC 更有效率:不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等。本人想当然认为AF_UNIX速度比127.0.0.1更快,为此鄙人进行了实验。

找一个比较大的文件,超过1G大小,然后
1。用AF_UNIX写客户端和服务端,由客户端读取文件,发送给AF_UNIX服务端,然后服务端写文件,看看用AF_UNIX传递一个文件需要多久。
2. 用127.0.0.1写客户端和服务端,由客户端读取文件,发送给127.0.0.1服务端,然后服务端写文件,看看用127.0.0.1传递一个文件需要多久。

废话不多说,直接上代码,先上AF_UNIX的:
AF_UNIX服务端(unixsocketserver.c):

#include <stdlib.h>  
#include <stdio.h>  
#include <stddef.h>  
#include <sys/socket.h>  
#include <sys/un.h>  
#include <errno.h>  
#include <string.h>  
#include <unistd.h>  
#include <ctype.h>   #define MAXLINE 80  char *socket_path = "/tmp/server.socket";  #define RECV_LEN 1000int main(void)  
{  fd_set readmask, exceptmask;struct timeval tv;int maxfd = FD_SETSIZE;int nready = 0;FILE *fp = fopen("/tmp/pull_desktop234_copy.flv", "w");if(fp == NULL){perror("fopen pull_desktop234_copy.flv failed");goto end;} char buf[RECV_LEN + 1];int readbyte, writebyte;struct sockaddr_un serun, cliun;  socklen_t cliun_len;  int listenfd, connfd, size;  if ((listenfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {  perror("socket error");  exit(1);  }  memset(&serun, 0, sizeof(serun));  serun.sun_family = AF_UNIX;  strcpy(serun.sun_path, socket_path);  size = offsetof(struct sockaddr_un, sun_path) + strlen(serun.sun_path);  unlink(socket_path);  if (bind(listenfd, (struct sockaddr *)&serun, size) < 0) {  perror("bind error");  exit(1);  }  printf("UNIX domain socket bound\n");  if (listen(listenfd, 20) < 0) {  perror("listen error");  exit(1);          }  printf("Accepting connections ...\n");  cliun_len = sizeof(cliun);         if ((connfd = accept(listenfd, (struct sockaddr *)&cliun, &cliun_len)) < 0){  perror("accept error");  goto end;  }time_t now, endtime;now = time(NULL);while(1){FD_ZERO(&readmask);FD_ZERO(&exceptmask);FD_SET(connfd, &readmask);FD_SET(connfd, &exceptmask);tv.tv_sec = 3;tv.tv_usec = 0;nready = select(maxfd, &readmask, NULL, &exceptmask, &tv);if(nready < 0){goto end;}if(nready == 0){printf("nready == 0\n");continue;}if(FD_ISSET(connfd, &readmask)){readbyte = recv(connfd, buf, RECV_LEN, 0);if(readbyte < 0){perror("readbyte < 0");goto end;}if(readbyte == 0){perror("readbyte == 0");goto end;}if(readbyte > 0){buf[readbyte] = 0;writebyte = fwrite(buf, 1, readbyte, fp);if(writebyte != readbyte){printf("writebyte(%d) != readbyte(%d)\n", writebyte, readbyte);goto end;}}}if(FD_ISSET(connfd, &exceptmask)){printf("select, exceptmask\n");goto end;}}  
end:endtime = time(NULL);printf("costs %d seconds\n", endtime - now);if(fp != NULL){fclose(fp);fp = NULL;}	close(connfd);close(listenfd);  return 0;  
}

AF_UNIX客户端(unixsocketclient.c):

#include <stdlib.h>  
#include <stdio.h>  
#include <stddef.h>  
#include <sys/socket.h>  
#include <sys/un.h>  
#include <errno.h>  
#include <string.h>  
#include <unistd.h>  #define SEND_LEN 1000char *client_path = "/tmp/client.socket";  
char *server_path = "/tmp/server.socket";  int main() {  struct  sockaddr_un cliun, serun;  int len;   int sockfd, n;  FILE *fp = fopen("/tmp/pull_desktop234.flv", "r");if(fp == NULL){perror("fopen pull_desktop234.flv failed");goto end;}   if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){  perror("client socket error");  exit(1);  }  // 一般显式调用bind函数,以便服务器区分不同客户端  memset(&cliun, 0, sizeof(cliun));  cliun.sun_family = AF_UNIX;  strcpy(cliun.sun_path, client_path);  len = offsetof(struct sockaddr_un, sun_path) + strlen(cliun.sun_path);  unlink(cliun.sun_path);  if (bind(sockfd, (struct sockaddr *)&cliun, len) < 0) {  perror("bind error");  exit(1);  }  memset(&serun, 0, sizeof(serun));  serun.sun_family = AF_UNIX;  strcpy(serun.sun_path, server_path);  len = offsetof(struct sockaddr_un, sun_path) + strlen(serun.sun_path);  if (connect(sockfd, (struct sockaddr *)&serun, len) < 0){  perror("connect error");  exit(1);  }  int sendbyte = 0;int alreadysendbyte = 0;char buf[SEND_LEN + 1];while((n = fread(buf, 1, SEND_LEN, fp)) > 0){sendbyte = send(sockfd, buf, n, 0);if(sendbyte == -1){perror("send error");goto end;}alreadysendbyte += sendbyte;while(alreadysendbyte < n){sendbyte = send(sockfd, buf + alreadysendbyte, n - alreadysendbyte, 0);if(sendbyte == -1){perror("send error");goto end;}alreadysendbyte += sendbyte;}}
end:if(fp != NULL){fclose(fp);fp = NULL;}close(sockfd);return 0;  
}

接着上127.0.0.1的:
127.0.0.1服务端(loopsocketserver.c):

#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>#define RECV_LEN 1000int main(){fd_set readmask, exceptmask;struct timeval tv;int maxfd = FD_SETSIZE;int nready = 0;FILE *fp = fopen("/tmp/pull_desktop234_copy.flv", "w");if(fp == NULL){perror("fopen pull_desktop234_copy.flv failed");goto end;} char buf[RECV_LEN + 1];int readbyte, writebyte;int serv_sock=socket(AF_INET,SOCK_STREAM,0);struct sockaddr_in serv_addr;memset(&serv_addr,0,sizeof(serv_addr));serv_addr.sin_family=AF_INET;serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);serv_addr.sin_port=htons(9990);bind(serv_sock,(struct sockaddr*)&serv_addr,sizeof(serv_addr));listen(serv_sock,5);struct sockaddr_in clnt_addr;socklen_t clnt_addr_size=sizeof(clnt_addr);int clnt_sock=accept(serv_sock,(struct sockaddr*)&clnt_addr,&clnt_addr_size);time_t now, endtime;now = time(NULL);while(1){FD_ZERO(&readmask);FD_ZERO(&exceptmask);FD_SET(clnt_sock, &readmask);FD_SET(clnt_sock, &exceptmask);tv.tv_sec = 3;tv.tv_usec = 0;nready = select(maxfd, &readmask, NULL, &exceptmask, &tv);if(nready < 0){goto end;}if(nready == 0){printf("nready == 0\n");continue;}if(FD_ISSET(clnt_sock, &readmask)){readbyte = recv(clnt_sock, buf, RECV_LEN, 0);if(readbyte < 0){perror("readbyte < 0");goto end;}if(readbyte == 0){perror("readbyte == 0");goto end;}if(readbyte > 0){buf[readbyte] = 0;writebyte = fwrite(buf, 1, readbyte, fp);if(writebyte != readbyte){printf("writebyte(%d) != readbyte(%d)\n", writebyte, readbyte);goto end;}}}if(FD_ISSET(clnt_sock, &exceptmask)){printf("select, exceptmask\n");goto end;}}
end: endtime = time(NULL);printf("costs %d seconds\n", endtime - now);if(fp != NULL){fclose(fp);fp = NULL;}close(clnt_sock);close(serv_sock);return 0;
}

127.0.0.1客户端(loopsocketclient.c):

#include<sys/socket.h>
#include<arpa/inet.h>
#include<stdio.h>
#include<string.h>
#include <errno.h>
#include <stdlib.h>#define SEND_LEN 1000int main(){int sock=socket(AF_INET,SOCK_STREAM,0);FILE *fp = fopen("/tmp/pull_desktop234.flv", "r");if(fp == NULL){perror("fopen pull_desktop234.flv failed");goto end;}   int n = 0;struct sockaddr_in serv_addr;memset(&serv_addr,0,sizeof(serv_addr));serv_addr.sin_family=AF_INET;serv_addr.sin_addr.s_addr=inet_addr("127.0.0.1");serv_addr.sin_port=htons(9990);if(connect(sock,(struct sockaddr*)&serv_addr,sizeof(serv_addr)) < 0){perror("connect failed");goto end;}int sendbyte = 0;int alreadysendbyte = 0;char buf[SEND_LEN + 1];while((n = fread(buf, 1, SEND_LEN, fp)) > 0){sendbyte = send(sock, buf, n, 0);if(sendbyte == -1){perror("send error");goto end;}alreadysendbyte += sendbyte;while(alreadysendbyte < n){sendbyte = send(sock, buf + alreadysendbyte, n - alreadysendbyte, 0);if(sendbyte == -1){perror("send error");goto end;}alreadysendbyte += sendbyte;}}
end:if(fp != NULL){fclose(fp);fp = NULL;}close(sock);return 0;
}

本人的缓冲区大小分为3种情况(文件大小为1.15G),上图代码片段缓冲区大小为1000字节:
缓冲区大小100字节:AF_UNIX传递完文件费时25秒,127.0.0.1传递完文件费时33秒
缓冲区大小1000字节:AF_UNIX传递完文件费时8秒,127.0.0.1传递完文件费时7秒
缓冲区大小10000字节:AF_UNIX传递完文件费时5秒,127.0.0.1传递完文件费时4秒

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

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

相关文章

如何实现MySQL的增删改查

MySQL是一种关系型数据库管理系统&#xff0c;提供了增删改查&#xff08;CRUD&#xff09;操作来管理数据库中的数据。下面是一些关于MySQL的增删改查的简要说明&#xff1a; 增加&#xff08;Create&#xff09;: 使用INSERT语句向数据库表中插入新的数据行。语法如下&#x…

git常用命令和开发常用场景

git命令 git init 创建一个空的git仓库或者重新初始化已有仓库 git clone [url] 将存储库克隆到新目录 git add 添加内容到索引 git status 显示工作树状态 git commit -m "" 记录仓库的修改 git reset 重置当前HEAD到指定的状态 git reset –-soft&#xff1a;…

2020架构真题(四十六)

、以下关于操作系统微内核架构特征的说法&#xff0c;不正确的是&#xff08;&#xff09;。 微内核的系统结构清晰&#xff0c;利于协作开发微内核代码量少&#xff0c;系统具有良好的可移植性微内核有良好的的伸缩性和扩展性微内核功能代码可以互相调用&#xff0c;性能很高…

3款国产办公软件,不仅好用,还支持linux国产操作系统

当提到国产办公软件并支持Linux国产操作系统时&#xff0c;以下是三款备受好评的软件&#xff1a; 1. WPS Office&#xff08;金山办公套件&#xff09; WPS Office是中国知名的办公软件套件&#xff0c;也是一款跨平台的应用程序。它包含文字处理、表格编辑和演示文稿等常见办…

06-进程间通信

学习目标 熟练使用pipe进行父子进程间通信熟练使用pipe进行兄弟进程间通信熟练使用fifo进行无血缘关系的进程间通信使用mmap进行有血缘关系的进程间通信使用mmap进行无血缘关系的进程间通信 2 进程间通信相关概念 2.1 什么是进程间通信 Linux环境下&#xff0c;进程地址空间…

STM32F030在使用内部参考电压 (VREFINT)时与STM32G070的区别

背景&#xff1a; 之前使用过STM32G070的内部参考电压来提升ADC采集的准确度&#xff08;STM32使用内部参考电压提高ADC采集准确度&#xff09;&#xff0c;所以本次使用STM32F030的芯片时直接把之前G070的代码拿过来用了&#xff0c;但是出现了问题。 查找资料发现两者不同&am…

STM32CubeMX学习笔记-USART_DMA

STM32CubeMX学习笔记-USART_DMA 一、DMA的概念二、数据传输方式普通模式循环模式 三、以串口方式讲解串口DMA方式发送函数&#xff1a;HAL_UART_Transmit_DMA串口DMA方式接收函数&#xff1a;HAL_UART_Receive_DMA获取未传输数据个数函数&#xff1a;__HAL_DMA_GET_COUNTER关闭…

解析navicate数据库密码

在线运行地址:代码在线运行 - 在线工具 <?php class NavicatPassword {protected $version 0;protected $aesKey libcckeylibcckey;protected $aesIv libcciv libcciv ;protected $blowString 3DC5CA39;protected $blowKey null;protected $blowIv null;public func…

spring boot整合Minio

MinIO 安装MinIo # 先创建minio 文件存放的位置 mkdir -p /opt/docker/minio/data# 启动并指定端口 docker run \-p 9000:9000 \-p 5001:5001 \--name minio \-v /opt/docker/minio/data:/data \-e "MINIO_ROOT_USERminioadmin" \-e "MINIO_ROOT_PASSWORDmini…

如何在Apache和Resin环境中实现HTTP到HTTPS的自动跳转:一次全面的探讨与实践

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

【MySQL】基本查询(二)

文章目录 一. 结果排序二. 筛选分页结果三. Update四. Delete五. 截断表六. 插入查询结果结束语 操作如下表 //创建表结构 mysql> create table exam_result(-> id int unsigned primary key auto_increment,-> name varchar(20) not null comment 同学姓名,-> chi…

PHP知识大全

PHP知识大全 1. 变量如何定义&#xff1f;如何检查变量是否定义&#xff1f;如何删除一个变量&#xff1f;怎样检测变量是否设置&#xff1f; $定义 isset()// 检测变量是否设置 defined&#xff08;&#xff09;// 检测常量是否设置unset()//销毁指定的变量 empty()// 检测…

解决yolo无法指定显卡的问题,实测v5、v7、v8有效

方法1 基本上这个就能解决了&#xff01;&#xff01;&#xff01; 在train.py的最上方加上下面这两行&#xff0c;注意是最上面&#xff0c;其次指定的就是你要使用的显卡 import os os.environ[CUDA_VISIBLE_DEVICES]6方法2&#xff1a; **问题&#xff1a;**命令行参数指…

<html dir=ltr>是什么意思?

<html dirltr>的意思是&#xff1a; 文字默认从左到右排列 说明&#xff1a; HTML--超级文本标记语言 dir 属性 -- (文字的)排列方式属性 取值&#xff1a; ltr -- 代表左到右的排列方式 rtl -- 代表右到左的排列方式 默认值:ltr 示例&#xff1a; ltr左到右的对…

C#:出题并判断

C#:出题并判断 //出题并判断 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms;namespace Test_…

# 解析Pikachu靶场:一个安全研究的练习场

引言 Pikachu靶场是一个非常流行的安全研究和渗透测试练习平台。这个环境包括多个安全漏洞&#xff0c;从基础的到高级的&#xff0c;供安全研究人员和渗透测试者进行实验和学习。在这篇博客中&#xff0c;我们将探讨Pikachu靶场的基本概念&#xff0c;功能&#xff0c;以及如…

使用安卓Termux+Hexo,手机也能轻松搭建个人博客网站

文章目录 前言1.安装 Hexo2.安装cpolar3.远程访问4.固定公网地址5.结语 前言 Hexo 是一个用 Nodejs 编写的快速、简洁且高效的博客框架。Hexo 使用 Markdown 解析文章&#xff0c;在几秒内&#xff0c;即可利用靓丽的主题生成静态网页。 下面介绍在Termux中安装个人hexo博客并…

NPDP考试应该怎么准备?考试攻略解析!

产品经理国际资格认证&#xff08;NPDP&#xff09;是国际公认的唯一的新产品开发专业认证&#xff0c;在全球20多个国家和地区范围内&#xff0c;充分践行&#xff0c;是集理论、方法与实践为一体的全方位知识体系。该知识体系包括新产品战略、产品组合管理、新产品开发流程、…

stl 输入输出流

标准输入输出流 头文件 iostream 从标准输入读取流 cin >> 从标准输出写入流 cout << get 系列函数 get 无参数&#xff1a;cin.get() 从指定的输入流中提取一个字符&#xff08;包括空白字符&#xff09;&#xff0c;若读取成功&#xff0c;返回该字符的 ASC…

论文分享 | 利用单模态自监督学习实现多模态AVSR

本次分享上海交通大学发表在 ACL 2022 会议 的论文《Leveraging Unimodal Self-Supervised Learning for Multimodal AVSR》。该论文利用大规模单模态自监督学习构建多模态语音识别模型。 论文地址&#xff1a; https://aclanthology.org/2022.acl-long.308.pdf 代码仓库&am…