本地socket通信

bilibili 就业班视频搬运 p55

1.作用

本地进程通信使用。 

2. 类型

2.1 面向连接的,类似于TCP 

(但不是TCP 呀!这里不需要什么协议了!)

socket函数的第二个参数填写 SOCK_STREAM

int sfd =socket(AF_UNIX, SOCK_STREAM, 0)

2.2 面向无连接的  类似UDP 

socket函数的第二个参数填写 SOCK_DGRAM

man 7 unix自己查看一下

3. 结构体解析

  A UNIX domain socket address is represented in the following structure:

           struct sockaddr_un {
               sa_family_t sun_family;               /* AF_UNIX */
               char        sun_path[108];            /* Pathname */
           };

地址结构体,  第一个成员sun_familiy  就填写af_unix 

第二个成员你填写你的socket文件的路径,一般都是当前文件夹下   “./你起的名字” 就行了

千万别事先创建 

4.第一次有瑕疵的代码

 4.1 有瑕疵的服务器代码 (后面改)

//本地socket通信 服务端代码
//local1SERFile 是我自己写的结构体地址的文件路径
//你可以随意命名 但记住这个名字#include <sys/types.h>  
#include <sys/socket.h>  
#include <sys/un.h>  
#include <unistd.h>  
#include <stdlib.h>  
#include <stdio.h> 
#include <ctype.h>int main(){//创建socket描述符int sfd =socket(AF_UNIX, SOCK_STREAM, 0);if (sfd<0){perror(" socket wrong\n");return -1;}//建立服务器的地址结构体/* struct sockaddr_un {sa_family_t sun_family;               AF_UNIX char        sun_path[108];             Pathname }; */struct sockaddr_un serad;  serad.sun_family = AF_UNIX;  strcpy(serad.sun_path, "./local1SERFile");  //绑定  注意结构体的成员不一样bind(sfd,(struct sockaddr*)&serad, sizeof(serad));//listenlisten(sfd,128);//建立客户端地址clienad;struct sockaddr_un clienad;  //注意,客户端的地址成员不用你写了socklen_t clilen = sizeof(clienad);//接受客户端的连接/这里应该不是高并发。    int newfd = accept(sfd, (struct sockaddr*)&clienad, &clilen);if (newfd<0) {perror("accept error\n");}char buf[1024]; while (1){//read  writememset (buf, 0x00, sizeof(buf));int n =read (newfd, buf, sizeof(buf));if (n<=0 ){printf("读到0个字符,客户断线\n"); break;}//大小写转换,并且返回给客户端for (int i=0;i<n;i++){buf[i] = toupper(buf[i]);}write (newfd, buf, n);}
close(newfd);
close (sfd);
return 0;
}

 4.2  如何测试

gcc -o  local1  local1.c

我把这个服务器代码编译成可执行文件local1

./local1     回车,服务端开始执行,

开启一个新终端,  nc  -U  ./local1SERFile    注意这个最后的文件名,是我写进代码里的,结构体的自定义的socket文件的名字,你写你自己的 

然后就可以通信了

命令netstat -anp | grep local  (local换成你自己编译的最终可执行文件名)查看网络状态

5. 改进

上面代码是不完善的,现在展示出错:

现在我们ctrl+C 退出客户端,过去服务端那边终端一看,服务端也自动退出了。符合预期。

但是重启客户端./local1 的时候,反复报错

accept error
: Invalid argument
读到0个字符,客户断线

???这是什么问题?因为前面说了

bind函数的地址参数里,如果文件已经存在那么久报错

看来是bind 函数报错,不是accept函数报错。

#include

int unlink(const char *pathname);

参数:

pathname:指向需解除连接的文件名。

返回说明:

成功执行时,返回0。失败返回-1,errno被设置。

注意只能对文件起作用!!!

这个函数不是直接删除文件!是删除硬链接!直到指向这个文件的硬链接=1 的时候,再执行这个函数就是真的 删掉了文件内容了

那么就在你的服务端代码第一行添上这句吧

经过添加unlink后,服务端和客户端又可以工作了

此时  用命令netstat -anp | grep local

(这个Local是因为我的最后编译成的可执行文件就叫local2    这样就能找到我的进程了,你写你自己的文件名字

看到客户端和服务器端的状态是;

unix  3      [ ]         STREAM     CONNECTED     70827    6223/./local2        ./local2FILE
unix  2      [ ACC ]     STREAM     LISTENING     70826    6223/./local2        ./local2FILE

6. 客户端代码 

这样就不用nc 命令测试了

6.1 客户端代码里没有bind 

这里服务器代码又小改了一下,所以都展示上

//本地socket通信 服务端代码
//ser.sock 是结构体地址的文件路径
#include <sys/types.h>  
#include <sys/socket.h>  
#include <sys/un.h>  
#include <unistd.h>  
#include <stdlib.h>  
#include <stdio.h> 
#include <ctype.h>int main(){unlink("./ser.sock");//创建socket描述符int sfd =socket(AF_UNIX, SOCK_STREAM, 0);if (sfd<0){perror(" socket wrong\n");return -1;}//建立服务器的地址结构体struct sockaddr_un serad;  serad.sun_family = AF_UNIX;  strcpy(serad.sun_path, "./ser.sock");  //绑定  注意结构体的成员不一样bind(sfd,(struct sockaddr*)&serad, sizeof(serad));//listenlisten(sfd,128);//建立客户端地址clienad;struct sockaddr_un clienad;  //注意,客户端的地址成员不用你写了socklen_t clilen = sizeof(clienad);int newfd = accept(sfd, (struct sockaddr*)&clienad, &clilen);if (newfd<0) {perror("accept error\n");}char buf[1024]; while (1){memset (buf, 0x00, sizeof(buf));int n =read (newfd, buf, sizeof(buf));printf("this is server,n=%d,receive %s\n", n, buf);	if (n<=0 ){printf("读到0个字符,客户断线\n"); break;}//大小写转换,并且返回给客户端for (int i=0;i<n;i++){buf[i] = toupper(buf[i]);}write (newfd, buf, n);}close(newfd);close (sfd);return 0;
} 

 客户端代码;客户端没有建立自己的客户socket文件;也能正常建立连接,获得变成了大写的字母

//本地socket通信 客户端代码
#include <sys/types.h>  
#include <sys/socket.h>  
#include <sys/un.h>  
#include <unistd.h>  
#include <stdlib.h>  
#include <stdio.h> 
#include <ctype.h>int main(){//创建socket描述符clientfd ,cfdint cfd =socket(AF_UNIX, SOCK_STREAM, 0);if (cfd<0){perror("client socket wrong\n");return -1;}//想要连接的服务器的地址结构体struct sockaddr_un toserad;  toserad.sun_family = AF_UNIX;//注意,socket文件,需要跟服务端的一样  strcpy(toserad.sun_path, "./ser.sock");    connect(cfd,(struct sockaddr*)&toserad, sizeof(toserad));char buf[1024];int n =0; while (1){memset (buf, 0x00, sizeof(buf));//STDIN_FILENOprintf("please type in:\n");n = read (STDIN_FILENO,buf,sizeof(buf));//发送数据	write (cfd, buf, n);memset(buf,0x00, sizeof(buf));//接收服务器的回馈n = read (cfd, buf,sizeof(buf));	if (n<=0 ){printf("this is client, receive no data\n"); break;}printf("this is client, receive %s\n",buf);}
close (cfd);
return 0;
}  

执行:

千万先启动服务端、再启动客户端!!!

客户端

please type in:
abc (你敲的abc进去)
this is client, receive ABC

服务端:

this is server,n=4,receive abc 

abc后面还有一个回车,所以服务端接受的是  4个字符。 

6.2 客户端代码里bind了自己的客户套接字文件

 服务代码跟6.1 里面一模一样,不写了

客户端代码展示。编译后,启动也是先服务端、再客户端、

//本地socket通信 客户端代码
//含有客户socket文件cli.sock  
//这篇客户代码使用了bind函数。
#include <sys/types.h>  
#include <sys/socket.h>  
#include <sys/un.h>  
#include <unistd.h>  
#include <stdlib.h>  
#include <stdio.h> 
#include <ctype.h>int main(){//创建socket描述符clientfd ,cfdint cfd =socket(AF_UNIX, SOCK_STREAM, 0);if (cfd<0){perror("client socket wrong\n");return -1;}//想要连接的服务器的地址结构体struct sockaddr_un toserad;  toserad.sun_family = AF_UNIX;//注意,socket文件,需要跟服务端的一样  strcpy(toserad.sun_path, "./ser.sock");  unlink ("./cli.sock");struct sockaddr_un cliad;cliad.sun_family = AF_UNIX;strcpy(cliad.sun_path, "./cli.sock");    int ret = bind(cfd,(struct sockaddr*)&cliad, sizeof(cliad));if (ret<0){perror("client bind wrong\n");return -1;}connect(cfd,(struct sockaddr*)&toserad, sizeof(toserad));char buf[1024];int n =0; while (1){memset (buf, 0x00, sizeof(buf));//STDIN_FILENOprintf("please type in:\n");n = read (STDIN_FILENO,buf,sizeof(buf));//发送数据	write (cfd, buf, n);memset(buf,0x00, sizeof(buf));//接收服务器的回馈n = read (cfd, buf,sizeof(buf));	if (n<=0 ){printf("this is client, receive no data\n"); break;}printf("this is client, receive %s\n",buf);}
close (cfd);
return 0;
} 

执行结果跟刚才一样的 

6.3 如何打印客户端地址

 客户端有了自己的套接字文件的话,服务端就能够找到客户端的socket文件路径。

换句话说服务端现在知道是谁(哪个socket文件) 在跟自己通信了

服务端的代码,在accept函数后面 加一行代码

 //打印客户端地址
    printf("客户端地址%s\n",clienad.sun_path);

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

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

相关文章

大模型相关术语

AGI&#xff08;Artificial General Intelligence&#xff09; 指通用人工智能&#xff0c;专注于研制像人一样思考、像人一样从事多种用途的机器。它与一般的特定领域智能&#xff08;如机器视觉、语音识别等&#xff09;相区分。 AIGC&#xff08;AI-Generated Content&…

tableau绘制雷达图

目标图形: 1. 数据准备 &#xff08;1&#xff09;原始数据 你要进行用雷达图比较的对象的各指标的数据。 (2) 处理后数据 在原数据的基础上添加对各指标进行区间的划分数据&#xff0c;也就是层级的划分。 2. 操作步骤 &#xff08;1&#xff09;数据转化 转化前&#xf…

Backtrader 文档学习- Broker - Cheat-On-Open

Backtrader 文档学习- Broker - Cheat-On-Open 1.概述 V1.9.44.116增加了Cheat On Open的支持。对于全押的人来说&#xff0c;这似乎是一个必需的功能&#xff0c;用bar的收盘价后进行计算&#xff0c;希望与开盘价相匹配。 当开盘价差距&#xff08;上涨或下跌&#xff0c;取…

streampark+flink一键整库或多表同步mysql到doris实战

streamparkflink一键整库或多表同步mysql到doris实战&#xff0c;此应用一旦推广起来&#xff0c;那么数据实时异构时&#xff0c;不仅可以减少对数据库的查询压力&#xff0c;还可以减少数据同步时的至少50%的成本&#xff0c;还可以减少30%的存储成本&#xff1b; streampar…

Vue.js 学习14 集成H265web.js播放器实现webpack自动化构建

Vue.js 学习14 集成H265web.js播放器实现webpack自动化构建 一、项目说明1. H265web.js 简介2. 准备环境 二、项目配置1. 下载 H265web.js2. 在vue项目里引入 H265web3. 设置 vue.config.js 三、代码引用1. 参照官方demo &#xff0c; 创建 executor.js2. 在 vue 页面里引用htm…

MongoDB数据库自动备份脚本

1.编写备份脚本 #!/bin/bash #backup MongoDB #mongodump 数据库备份echo "-----------数据库备份开始-------------" #数据库mongodump备份工具 DUMP/home/dbbackup/mongodb4.4/bin/mongodump #临时备份目录 OUT_DIR/home/dbbackup/mongodb_bak_now #历史备份列表…

K8S网络

一、介绍 k8s不提供网络通信&#xff0c;提供了CNI接口(Container Network Interface&#xff0c;容器网络接口)&#xff0c;由CNI插件实现完成。 1.1 Pod通信 1.1.1 同一节点Pod通信 Pod通过虚拟Ethernet接口对&#xff08;Veth Pair&#xff09;与外部通信&#xff0c;Veth…

有向图查询所有环,非递归

图&#xff1a; 有向图查询所有环&#xff0c;非递归&#xff1a; import java.util.*;public class CycleTest {private final int V; // 顶点数private final List<List<Integer>> adjList; // 邻接表public CycleTest(int vertices) {this.V vertices;this.…

C++ : 类的简单介绍(四)——析构函数

概念&#xff1a; 与构造函数功能相反&#xff0c;析构函数不是完成对对象本身的销毁&#xff0c;局部对象销毁工作是由 编译器完成的。 而对象在销毁时会自动调用析构函数&#xff0c;完成对象中资源的清理工作。 特征&#xff1a; 1. 析构函数名是在类名前加上字符 ~ 2. …

java+springboot电影订票选座及评论网站影评系统ssm+vue

广大观影消费者需要知道自己的空闲时间&#xff0c;在自己可以接受的地理距离范围内&#xff0c;是否有感兴趣的影片可供观看&#xff0c;也需要清楚哪家影院在销售自己需要的电影票&#xff1b;同时手握电影排期及上映信息的电影院的运营者也急需根据消费者的观影需求实时调整…

C++中的结构体内存对齐规则及原因

一、结构体内存对齐规则 1.第一个成员在结构体偏移量为0的地址处 2.其他成员变量要对齐到对齐数的整数倍地址处&#xff08;对齐数 min&#xff08;对齐数&#xff0c;变量大小&#xff09;&#xff09; &#xff08;VS下默认对齐数为8&#xff0c;也可以自定义对齐数&#…

【笔记】CSDN文本编辑操作(持续更新中......)

文章目录 1、修改字体颜色和字号2、首行悬进两个字符3、图片居中4、字体、文字颜色、居中5、高亮6、重点标注7、加粗 1、修改字体颜色和字号 <html><head><meta http-equiv"Content" content"text/html;charsetutf-8" /><title>修…

互联网医院开发:未来医疗的新篇章

随着科技的飞速发展&#xff0c;互联网已经深入到我们生活的方方面面&#xff0c;而医疗领域也不例外。近年来&#xff0c;互联网医院的发展已经成为医疗行业的新趋势&#xff0c;为患者提供了更为便捷、高效的医疗服务。本文将探讨互联网医院开发的重要性、技术实现以及未来发…

pnpm、npm、yarn 包管理工具

1、npm 关键词&#xff1a;软件包管理器、命令行工具、一个社区和一个平台 npm&#xff08;Node Package Manager&#xff09;是一个用于Node.js环境的软件包管理器。它是一个命令行工具&#xff0c;用于安装、升级、删除和管理JavaScript软件包。npm最初是随同Node.js一起发布…

【30秒看懂大数据】变量

简单说 变量是指研究或观察中可能发生变化的事物、属性或特征&#xff0c;它们可以用来描述数据或现象的不同方面。 举例理解 一位热衷于烹饪的大厨老李&#xff0c;经常尝试不同的菜肴来满足不同顾客的口味。 1. 老李明白&#xff0c;每种食材都等同于一个重要的变量…

【报错记录】mybatis映射对应的类没有无参构造引发的问题

写了一个联表查询文件记录及文件标签的SQL&#xff1a; <select id"selectDataFileVoList" resultMap"dataFileVo">SELECTdf.id AS id,df.file_name,df.file_url,df.file_size,df.extend_name,df.category_name,df.file_extracts,df.create_time,df…

王道_数据结构 1.2_2_算法的时间复杂度

1.2_2_算法的时间复杂度 一、为什么要事先预估算法时间开销二、时间复杂度的计算与技巧1、化简“算法时间开销”的计算方式的依据2、常用技巧&#xff08;1&#xff09;加法、乘法规则&#xff08;2&#xff09;时间复杂度的数量级阶数排行 3、计算时间复杂度的结论与步骤&…

TMC电池供电方案推荐

静音、小巧、精确、高效的构建模块改变了电机在电池供电设备中的使用方式。从恒温散热器阀&#xff0c;到现实捕捉设备和电动工具&#xff0c;再到医疗健康应用&#xff0c;激发丰沛想象力&#xff0c;将可靠概念运用于电池供电设备&#xff0c;为消费者和专业人士带来便利。 …

Klocwork 2023.4发布:问题匹配算法升级,编码标准全面支持!

Klocwork 2023.4 的新增功能 Klocwork 2023.4 改进了问题匹配的算法&#xff0c;为桌面端和CI集成构建之间的结果提供了更大的一致性&#xff0c;以及连续构建之间的问题匹配。Klocwork的最新版本还改进了C/C语言的分析引擎&#xff0c;减少了误报/漏报&#xff0c;跨过程跟踪…

C#,洛布数(Lobb Number)的计算方法与源代码

1 洛布数&#xff08;Lobb Number&#xff09; 在组合数学中&#xff0c;洛布数&#xff08;Lobb Number&#xff09;L(m&#xff0c;n)计算nm开括号的排列方式&#xff0c;以形成一个有效的平衡括号序列的开始。 Lobb数由两个非负整数m和n参数化&#xff0c;其中n>m>0。…