linux进程间通信---本地socket套接字(一)---一个server对应一个client

2023-11-09

**
先给自己打个广告,本人的微信公众号正式上线了,搜索:张笑生的地盘,主要关注嵌入式软件开发,股票基金定投,足球等等,希望大家多多关注,有问题可以直接留言给我,一定尽心尽力回答大家的问题。想要获取完整源码的,关注公众号后回复“socket1”即可。
在这里插入图片描述

一 what

**
socket套接字也是一种文件格式,只是和管道文件一样,它是一种伪文件,存在于内核的缓冲区中,大小不变,一直是0.
套接字一定是成对出现的,有server套接字,就一定有client套接字,它是一种全双工通信方式,分别有读写缓冲区
通信框图

            cs架构   (bs架构,browser server)
        服务器 server             客户端client
        1. 请求协议版本           1. 请求协议版本
        2. 创建socket            2. 创建socket
        3. 创建协议地址族         3. 获取服务器协议地址族
              ip地址
              网络端口
              通信协议
        4. 绑定
        5. 监听
        6. 等待客户端连接         4. 连接服务器
        7. 通信                  5. 通信
        8. 关闭socket            6. 关闭socket
        9. 清理协议版本           7. 清理协议版本

和套接字相关的几个地址结构体如下,struct sockaddr用来描述ipv4地址协议
在这里插入图片描述
和地址转换相关的几个函数

ip地址转换函数
inet_pton    192.168.1.24 --------------> 网络字节序
/* 
 * 参数 af,网络ip地址的版本,ipv4或ipv6
 *      src 192.168.1.24
 *      dst 网络字节序
 */
int inet_pton(int af, const char *src, void *dst);

inet_ntop    网络字节序 --------------> 点分十进制
/* 
 * 参数 af,网络ip地址的版本,ipv4或ipv6
 *      src 网络字节序
 *      dst 192.168.1.24
 *      size 字符串dst长度
 */
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);

**

二 why

**

**

三 how

**
本地套接字用于实现本机进程间通信,有tcp和udp类似两种,我们以类似tcp方式举例
在这里插入图片描述

主机 server
1. 创建socket
    int ifd = socket(AF_LOCAL, sock_stream, 0);   //AF_UNIX也可以,AF_INET是指网络套接字
2. 绑定 struct sockaddr_un
    struct sockaddr_un serv;
    serv.sun_family = AF_LOCAL;
    strcpy(serv.sun_path, "server.socket");   //server.socket此时还不存在的,它什么时候会存在呢
    bind(ifd, (struct sockaddr *)&serv, sizeof(serv)); //绑定成功,server.socket这个文件就会被创建
3. 设置监听
    listen()
4. 等待接收连接请求
    struct sockaddr_un client;
    int len = sizeof(client);
    int cfd = accept(ifd, &client, &len);
5. 通信
    send     //发送数据
    recv     //接收数据
6. 断开连接

代码如下

server.c

int main(int argc, char *argv[])
{
    ......

    //创建socket
    lfd = socket(AF_LOCAL, SOCK_STREAM, 0);
    if (lfd == -1) {
        perror("socket error");
        return -1;
    }

    //初始化server信息
    serv.sun_family = AF_LOCAL;
    strcpy(serv.sun_path, "server.sock");

    //绑定
    ret = bind(lfd, (struct sockaddr *)&serv, sizeof(serv));
    if (ret == -1) {
        perror("bind error");
        return -1;
    }

    //设置监听,设置能够同时和服务端连接的客户端数量
    ret = listen(lfd, 36);
    if (ret == -1) {
        perror("listen error");
        return -1;
    }

    //等待客户端连接
    cfd = accept(lfd, (struct sockaddr *)&client, &len);
    if (cfd == -1) {
        perror("accept error");
        return -1;
    }
    printf("=====client bind file:%s\n", client.sun_path);
    
    while (1) {
        recvlen = recv(cfd, buf, sizeof(buf), 0);
        ......
    }
    
    ......
}
客户端client
1. 创建socket
    int fd = socket(AF_LOCAL, sock_stream, 0);   //AF_UNIX也可以,AF_INET是指网络套接字
2. 绑定套接字文件
    struct sockaddr_un client;
    client.sun_family = AF_LOCAL;
    strcpy(client.sun_path, "client.socket");   //client.socket此时还不存在的,它什么时候会存在呢
    bind(ifd, (struct sockaddr *)&client, len); //绑定成功,server.socket这个文件就会被创建
3. 连接服务器
    struct sockaddr_un serv;
    serv.sun_family = AF_LOCAL;
    strcpy(serv.sun_path, "server.socket");   //server.socket此时还不存在的,它什么时候会存在呢
    connect(fd, &serv, sizeof(serv))
4. 通信
    recv
    send
5. 关闭
    close

代码如下

client.c

int main(int argc, char *argv[])
{
    ......

    //创建socket
    lfd = socket(AF_LOCAL, SOCK_STREAM, 0);
    if (lfd == -1) {
        perror("socket error");
        return -1;
    }

    //给客户端绑定一个套接字文件
    client.sun_family = AF_LOCAL;
    strcpy(client.sun_path, "client.sock");
    ret = bind(lfd, (struct sockaddr *)&client, sizeof(client));
    if (ret == -1) {
        perror("bind error");
        return -1;
    }

    //初始化server信息
    serv.sun_family = AF_LOCAL;
    strcpy(serv.sun_path, "server.sock");
    //连接
    connect(lfd, (struct sockaddr *)&serv, sizeof(serv));

    while (1) {
        fgets(buf, sizeof(buf), stdin);
        send(lfd, buf, strlen(buf)+1, 0);

        recv(lfd, buf, sizeof(buf), 0);
        printf("recv buf %s\n", buf);
    }

    ......
}

分别编译后,先运行./server,我们发现在当前目录下创建了一个serve.sock的套接字文件,文件类型位s
在这里插入图片描述
然后运行./client,同样发现创建了一个套接字文件client.sock,然后在client输入信息,就会在server端接收到信息了。
但是我们会遇到一个问题,当我们停止./server或者./client,在运行./server或者./client,会发现一个错误提示
在这里插入图片描述
这是因为套接字文件已经存在,不能再bind了,我们需要修改源程序,在bind之前,加上unlink,就是说如果套接字文件存在,需要先删除套接字文件。

server.c


int main(int argc, char *argv[])
{
    ......

    //创建socket
    lfd = socket(AF_LOCAL, SOCK_STREAM, 0);
    if (lfd == -1) {
        perror("socket error");
        return -1;
    }
    
    //如果套接字文件存在,存删除套接字文件
    unlink("server.sock");

    //初始化server信息
    serv.sun_family = AF_LOCAL;
    strcpy(serv.sun_path, "server.sock");

    //绑定
    ret = bind(lfd, (struct sockaddr *)&serv, sizeof(serv));
    if (ret == -1) {
        perror("bind error");
        return -1;
    }

    //监听
    ret = listen(lfd, 36);
    if (ret == -1) {
        perror("listen error");
        return -1;
    }

    //等待客户端连接
    cfd = accept(lfd, (struct sockaddr *)&client, &len);
    if (cfd == -1) {
        perror("accept error");
        return -1;
    }
    printf("=====client bind file:%s\n", client.sun_path);
    
    while (1) {
        recvlen = recv(cfd, buf, sizeof(buf), 0);
        ......
    }
    
    ......
}
client.c


int main(int argc, char *argv[])
{
    ......

    //创建socket
    lfd = socket(AF_LOCAL, SOCK_STREAM, 0);
    if (lfd == -1) {
        perror("socket error");
        return -1;
    }

    //如果套接字文件存在,存删除套接字文件
    unlink("client.sock");

    //给客户端绑定一个套接字文件
    client.sun_family = AF_LOCAL;
    strcpy(client.sun_path, "client.sock");
    ret = bind(lfd, (struct sockaddr *)&client, sizeof(client));
    if (ret == -1) {
        perror("bind error");
        return -1;
    }

    //初始化server信息
    serv.sun_family = AF_LOCAL;
    strcpy(serv.sun_path, "server.sock");
    //连接
    connect(lfd, (struct sockaddr *)&serv, sizeof(serv));

    while (1) {
        fgets(buf, sizeof(buf), stdin);
        send(lfd, buf, strlen(buf)+1, 0);

        recv(lfd, buf, sizeof(buf), 0);
        printf("recv buf %s\n", buf);
    }

    ......
}

想要获取完整源码的,请关注微信公众号:嵌入式Linux江湖,关注公众号后回复“socket1”即可

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux进程间通信---本地socket套接字(一)---一个server对应一个client 的相关文章

  • 远程 ssh 命令:第一个回显输出丢失

    我试图通过 ssh 1 liner 调用在远程机器上运行多个命令 方法是将它们指定为传递给 bash c 的分号分隔字符串 它适用于某些情况 但不适用于其他情况 看一下这个 Note the echo 1 output is lost ba
  • MYSQL插入GB大小的巨大SQL文件

    我正在尝试创建 Wikipedia DB 副本 大约 50GB 但在处理最大的 SQL 文件时遇到问题 我使用 linux split 实用程序将 GB 大小的文件拆分为 300 MB 的块 例如 split d l 50 enwiki 2
  • 将一个文件写入.c中的另一个文件

    我有一个读取文件然后将其内容复制到另一个文件的代码 我需要使其仅复制每 20 个符号 然后跳过 10 个符号 然后再次跳过 20 个符号 依此类推 我必须使用 lseek 函数 但我不知道如何将所有这些放入循环中来执行此操作 main ar
  • 除了 iptables 之外还有数据包管理实用程序吗? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一个 Linux 实用程序 它可以根据一组规则更改网络数据包的有效负载 理想情况下 我会使用
  • 页面错误陷阱的成本

    我有一个应用程序 它定期 每 1 或 2 秒后 通过分叉自身来获取检查点 因此 检查点是原始进程的一个分支 它一直保持空闲状态 直到原始进程发生某些错误时被要求启动 现在我的问题是fork的写时复制机制的成本有多大 每当原始进程写入内存页面
  • 让“git pull”在拉取不同分支时要求确认

    当同时处理许多项目和分支时 我偶尔会犯一些愚蠢的错误 比如拉入错误的分支 例如在分支上master I did git pull origin dangerous code并且有一段时间没有注意到这一点 这个小错误造成了很大的混乱 当我尝试
  • 如何从 C 文件更改终端中的目录

    如何从 C 程序更改将在终端上生效的目录 实际上不要告诉 system 函数或 chdir 函数 这些仅适用于 C 中的进程或子 shell 假设我正在从 bash shell 执行一个 C 程序 其进程 ID 为 10223 那么 我可以
  • 如何修改s_client的代码?

    我正在玩apps s client c in the openssl源代码 我想进行一些更改并运行它 但是在保存文件并执行操作后 我的更改没有得到反映make all or a make 例如 我改变了sc usage函数为此 BIO pr
  • 当存在点和下划线时,使用 sed 搜索并替换

    我该如何更换foo with foo sed 只需运行 sed s foo foo g file php 不起作用 逃离 sed s foo foo g file php Example cat test txt foo bar sed s
  • 当我通过 shell 脚本创建 .txt 文件时,为什么文件名末尾出现问号? [复制]

    这个问题在这里已经有答案了 我正在编写一个 shell 脚本 我应该在其中创建 1 个文本文件 当我这样做时 文件名末尾出现一个问号 是什么原因 我正在 bash 脚本中尝试以下方法 1 grep ERROR a1 gt text txt
  • sed 仅最后一个匹配模式

    我想sed仅文本文件的最后一个匹配模式 输入文件 boy boy girl boy 输出文件 boy boy girl boys 一种方法是反转文件 仅替换第一个匹配项 然后再次反转 tac
  • Nasm 打印到下一行

    我用 nasm Assembly 编写了以下程序 section text global start start Input variables mov edx inLen mov ecx inMsg mov ebx 1 mov eax 4
  • 如何删除树莓派的相机预览

    我在我的 raspberryPi 上安装了 SimpleCv 并安装了用于使用相机板的驱动程序 uv4l 驱动程序 现在我想使用它 当我在 simpleCV shell Camera 0 getImage save foo jpg 上键入时
  • 无法为 Python 3.4 创建工作虚拟环境

    I 安装Python 3 4 2 https docs python org 3 using unix html building python和我的 Linux Mint 17 1 中的 Virtualenv 12 0 5 然后我尝试创建
  • 我在哪里可以学习如何使 C++ 程序与操作系统 (Linux) 交互

    我是一个 C 初学者 我想创建与操作系统交互的小程序 使用 Kubuntu Linux 到目前为止 我还没有找到任何教程或手册来让 C 与操作系统交互 在 PHP 中 我可以使用命令 exec 或反引号运算符来启动通常在控制台中执行的命令
  • 对 sf:: 的未定义引用

    我想用 C 制作 GUI 应用程序 发现 SFML 是一个不错的选择 幸运的是 我使用的是 Linux 所以 SFML 2 4 已经安装在我的系统上 所以我开始搜索一些教程并找到了一个制作简单窗口的教程 但是当我运行代码时 出现错误 提示未
  • 如何使用 bash 脚本关闭所有终端,在每个终端中有效地按 Ctrl+Shift+Q

    我经常打开许多终端 其中一些正在运行重要的进程 例如服务器 而另一些则没有运行任何东西并且可以关闭 如果您按 重要 则会弹出确认提示Cntrl Shift Q在其中 如下所示 我想要一个 bash 脚本 它可以关闭所有终端 但将 重要 终端
  • ARM 系统调用的接口是什么?它在 Linux 内核中的何处定义?

    我读过有关 Linux 中的系统调用的内容 并且到处都给出了有关 x86 架构的描述 0x80中断和SYSENTER 但我无法追踪 ARM 架构中系统调用的文件和进程 任何人都可以帮忙吗 我知道的几个相关文件是 arch arm kerne
  • /proc/PID 文件格式

    我想从中检索一些流程信息 proc目录 我的问题如下 中的文件是否有标准格式 proc PID 例如 有这个proc PID status文件与Name t ProcName在第一行 我可以在其他地方用空格代替这个文件吗 t或者类似的东西
  • 将 stdout 作为命令行 util 的文件名传递?

    我正在使用一个命令行实用程序 该实用程序需要传递文件名以将输出写入 例如 foo o output txt 它唯一写入的东西stdout是一条消息 表明它运行成功 我希望能够通过管道传输写入的所有内容output txt到另一个命令行实用程

随机推荐

  • SQL Server与Java的类型对应,Char用setString设值

    表列出了基本 SQL Server JDBC 和 Java 编程语言数据类型之间的默认映射 SQL Server 类型 JDBC 类型 java sql Types Java 语言类型 bigint BIGINT long timestam
  • Java实现桶排序

    桶排序 使用额外空间 以空间换时间思想 因此时间复杂度为O n m 1 1 基本思想 桶排序是所有排序算法中最快 也是最简单的排序算法 基本思想是在知道所有待排元素的范围后 准备和这个范围同样数量的桶 并将元素放在对应的桶中 如待排元素为
  • java焦点图_基于JavaScript实现焦点图轮播效果

    不管是高校的网站还是电商的页面 焦点图的切换和轮播应该是一项不可或缺的应用 今天把焦点图轮播制作的技术要点做下笔记 以供日后查看 一 结构层 HTML 焦点图的HTML结构很简单 就是一个父容器 id box 包含三个子容器 分别存放图片
  • lua:table转json字符串

    table转字符串 function table2JsonString objTable local jsonString jsonString local t type objTable if t number then jsonStri
  • harbor修改配置文件后重启

    docker compose down prepare docker compose up d 转载于 https www cnblogs com wang lei p 11540792 html
  • 自从AndroidStudio更新到2.2,就有了CMake和传统JNI两种开发NDK的方法,主要就是在目录结构和build.gradle上的区别,下面我们将分别介绍目录区别和build.gr

    http blog csdn net u012527560 article details 51752070 自从AndroidStudio更新到2 2 就有了CMake和传统JNI两种开发NDK的方法 主要就是在目录结构和build gr
  • 使用JSON

    JSON Javascript Object Notion Javascript对象表示法 JSON是Javascript对象表示法的一个子集 它必然使用了Javascrip对象表示法中的所有相同的规则和基础类型 JSON可以表示对象的实例
  • 实战wxPython:044 - 高级控件之HtmlWindow

    本文介绍如何在Python的GUI工具中嵌入HTML页面 wxPython的wx html和wx html2模块支持解析和显示HTML文件内容 wx html HtmlWindow对象是一个通用的HTML浏览器 但不是一个全功能的浏览器 所
  • Go语言基础整理集合

    什么是Go语言 go语言是一门静态强类型语言 什么是动态和静态 可以理解为解释型和编译型 python 动态解释型语言 一边编译一边执行 golang java 静态编译型语言 必须先将文件编译成可执行文件后才能运行 什么是强类型语言 强制
  • qt ini 文件读写以及 节点的遍历

    qt 的配置文件一般都用ini文件 在此我记录下使用方法 ini 组成简介 INI文件由节点 键 值组成 如下面代码中 fileSetting gt setValue fileSave savePath filePath 节点 fileSa
  • mysql之sql_mode参数

    参数sql mode用来设置mysql中语法校验的严格程度 用此来保证数据的准确性 常用的可选值说明如下 参数值 说明 ONLY FULL GROUP BY GROUP BY聚合查询中如果SELECT中的列没在GROUP BY子句中 那么这
  • 人脸关键点序号106个 98个

    106关键点 forked from 北京智云视图科技有限公司 HyperLandmark 68和106对应 从0开始编号 17 19 21 28 22 24 26 74 36 94 39 59 42 27 45 20 31 31 35 9
  • 2019-CVPR 缺陷/瑕疵检测论文介绍及基于pytorch实现的代码

    Segmentation Based Deep Learning Approach for Surface Defect Detection的介绍和实现 本文介绍 论文解析 1 INTRODUCTION 2 Related Work 3 S
  • 基于Chatbot UI 实现ChatGPT对话-V1.3-预告

    先讲一个悲伤的故事 小红书被封号了 emo 给俺点点关注吧 这次一定好好发言 迷茫的21世纪的新青年 一 预告图 自定义随机量 让回复按需设置 二 更新功能 随机量 参数名 Temperature 温度 我更愿意称之为随机量 它根据调的数值
  • Python报错及解决办法一

    问题一 C Users asus gt print Hello World 无法初始化设备 PRN 解决办法 先执行python解释器 再执行python代码 C Users asus gt python Python 3 10 6 tag
  • ValueError: shapes (1,3) and (100,1) not aligned: 3 (dim 1) != 100 (dim 0)

    ValueError shapes 1 3 and 100 1 not aligned 3 dim 1 100 dim 0 出现这个错误 是你数据的维度不对 这个问题是出现在写logistic Regression 代码时出现的 用scip
  • C++拷贝构造函数

    注意 1 当函数的参数为类的对象时 那么在函数的形参与调用这个函数时的实参并不一定内容一模一样 因为是调用的拷贝构造函数 因此也有可能自定义的拷贝构造函数会导致两个对象的内容不一样 2 拷贝构造函数 只对非静态属性进行拷贝 拷贝构造函数调用
  • OpenCV中读取摄像头

    人脸识别首先要做的就是摄像头数据的读取 这里OpenCV很好的实现了摄像头数据的读取 在OpenCV1 x中用到的函数是 1 打开摄像头或视频文件 CvCapture cvCreateCameraCapture int index inde
  • ubuntu18.04安装dconf-editor以及设置root远程终端

    今天我们将学习一下dconf editor和root远程 方便我们在工作的时候 客户需要安装软件 我们就不用那么麻烦的跑道现场去给客户安装 这也是给咱们运维人员图个方便 dconf editor介绍 这个只是简单配置存储系统 图形编辑器 可
  • linux进程间通信---本地socket套接字(一)---一个server对应一个client

    先给自己打个广告 本人的微信公众号正式上线了 搜索 张笑生的地盘 主要关注嵌入式软件开发 股票基金定投 足球等等 希望大家多多关注 有问题可以直接留言给我 一定尽心尽力回答大家的问题 想要获取完整源码的 关注公众号后回复 socket1 即