C语言UNIX域套接字CS模型

实验目标:

1 实现基于流的unix域套接字通信cs模型

2 实现基于数据报的unix域套接字通信cs模型

3 可以观察到CS两端的完整启动退出流程,为了实现这一目标仅进行一次通信

实验心得:

1 使用unlink避免地址冲突 清理资源

2 传统udp在首次sendto时系统临时分配端口,在套接字关闭|程序终止|显式解绑时端口生命周期结束,而unix域套接字则需要手动绑定,否则客户端无法收到服务器的回信

3 复制文件路径时,sun_path的长度无法更改,容易出现越界的情况

基于流:

#define _GNU_SOURCE
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#include <string.h>
#include <unistd.h>#define SOCK_PATH "/home/u22/socket/addr1"
// 服务端
int main()
{int server_sockfd, client_sockfd;struct sockaddr_un server_sockaddr, client_sockaddr;memset(&server_sockaddr, 0, sizeof(server_sockaddr));memset(&client_sockaddr, 0, sizeof(client_sockaddr));socklen_t client_sockaddr_len = sizeof(client_sockaddr);ssize_t send_bytes, recv_bytes;char send_buf[1024] = "server say : How can I help you today ?";char recv_buf[1024] = {0};// unix域套接字 使用流式传输,不能叫TCPserver_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);if (server_sockfd == -1){perror("socket");}server_sockaddr.sun_family = AF_UNIX;strcpy(server_sockaddr.sun_path, SOCK_PATH);// 为什么要删除这个文件?因为再次启动代码将无法访问这个文件unlink(SOCK_PATH);if ((bind(server_sockfd, (struct sockaddr *)&server_sockaddr, sizeof(server_sockaddr))) == -1){perror("bind");}if (listen(server_sockfd, 16) == -1){perror("listen");}printf("waiting for connect...\n");// accept返回后将收到客户端地址信息client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_sockaddr, &client_sockaddr_len);if (client_sockfd == -1){perror("accept");}// 同tcp一样 recv send使用accept返回的socket通信recv_bytes = recv(client_sockfd, recv_buf, sizeof(recv_buf), 0);if (recv_bytes == -1){perror("recv");}if (recv_bytes > 0){printf("%s\n", recv_buf);}send_bytes = send(client_sockfd, send_buf, strlen(send_buf), 0);if (send_bytes == -1){perror("send");}if (send_bytes > 0){printf("%s\n", send_buf);}close(client_sockfd);close(server_sockfd);printf("server close\n");//用完了 还要删一遍unlink(SOCK_PATH);return 0;
}
#define _GNU_SOURCE
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#include <string.h>
#include <unistd.h>#define SOCK_PATH "/home/u22/socket/addr1"
//客户端
int main()
{int client_sockfd;struct sockaddr_un server_sockaddr;memset(&server_sockaddr, 0, sizeof(server_sockaddr));ssize_t send_bytes, recv_bytes;char send_buf[1024] = "client say : hello server !";char recv_buf[1024] = {0};//创建基于流的unix域套接字client_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);if (client_sockfd == -1){perror("socket");}server_sockaddr.sun_family = AF_UNIX;strcpy(server_sockaddr.sun_path, SOCK_PATH);//尝试连接serverprintf("connect server...\n");if ((connect(client_sockfd, (struct sockaddr *)&server_sockaddr, sizeof(server_sockaddr))) == -1){perror("connect");}//与TCP一样 使用socket()返回的socket通信send_bytes = send(client_sockfd, send_buf, strlen(send_buf), 0);if (send_bytes == -1){perror("send");}printf("%s\n", send_buf);recv_bytes = recv(client_sockfd, recv_buf, sizeof(recv_buf), 0);if (recv_bytes == -1){perror("recv");}printf("%s\n", recv_buf);close(client_sockfd);printf("client close\n");return 0;
}

基于数据报:

#define _GNU_SOURCE
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#include <string.h>
#include <unistd.h>#define SOCK_PATH "/home/u22/socket/addr2"int main()
{int server_sockfd;struct sockaddr_un server_sockaddr, client_sockaddr;memset(&server_sockaddr, 0, sizeof(server_sockaddr));memset(&client_sockaddr, 0, sizeof(client_sockaddr));socklen_t client_sockaddr_len = sizeof(client_sockaddr);ssize_t send_bytes, recv_bytes;char send_buf[1024] = "server say : How can I help you today ?";char recv_buf[1024] = {0};// unix域套接字 使用数据报传输,不能叫UDPserver_sockfd = socket(AF_UNIX, SOCK_DGRAM, 0);if (server_sockfd == -1){perror("socket");}// 无法再次访问此文件,必须删除unlink(SOCK_PATH);server_sockaddr.sun_family = AF_UNIX;// 容易越界,本系统为108字节strncpy(server_sockaddr.sun_path, SOCK_PATH, sizeof(server_sockaddr.sun_path));// 不bind,peer使用sendto也可以正常发送,但是本endpoint无法接收if ((bind(server_sockfd, (struct sockaddr *)&server_sockaddr, sizeof(server_sockaddr))) == -1){perror("bind");}printf("waiting for recv...\n");// 接收的客户端地址信息存在client_sockaddr中,供sendto使用recv_bytes = recvfrom(server_sockfd, recv_buf, sizeof(recv_buf),0, (struct sockaddr *)&client_sockaddr, &client_sockaddr_len);if (recv_bytes == -1){perror("recv");}if (recv_bytes > 0){printf("%s\n", recv_buf);}send_bytes = sendto(server_sockfd, send_buf, strlen(send_buf),0, (struct sockaddr *)&client_sockaddr, client_sockaddr_len);if (send_bytes == -1){perror("send");}if (send_bytes > 0){printf("%s\n", send_buf);}close(server_sockfd);printf("server close\n");// 用完删除SOCK_PATH这个文件unlink(SOCK_PATH);return 0;
}
#define _GNU_SOURCE
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#include <string.h>
#include <unistd.h>
// 客户端使用的socket文件
#define SOCK_PATH_C "/home/u22/socket/addr3"
// 服务器使用的socket文件
#define SOCK_PATH_S "/home/u22/socket/addr2"
// 客户端
int main()
{int client_sockfd;struct sockaddr_un server_sockaddr, client_sockaddr;memset(&server_sockaddr, 0, sizeof(server_sockaddr));memset(&client_sockaddr, 0, sizeof(client_sockaddr));socklen_t server_sockaddr_len = sizeof(server_sockaddr);ssize_t send_bytes, recv_bytes;char send_buf[1024] = "client say : hello server !";char recv_buf[1024] = {0};// 基于数据报的unix域套接字client_sockfd = socket(AF_UNIX, SOCK_DGRAM, 0);if (client_sockfd == -1){perror("socket");}// 必须删除,否则下次不让用unlink(SOCK_PATH_C);client_sockaddr.sun_family = AF_UNIX;// 容易越界,本系统为108strncpy(client_sockaddr.sun_path, SOCK_PATH_C, sizeof(client_sockaddr.sun_path));// 传统udp在首次sendto时系统临时分配端口,在套接字关闭|程序终止|显式解绑时端口生命周期结束// 而unix域套接字则需要手动绑定if ((bind(client_sockfd, (struct sockaddr *)&client_sockaddr, sizeof(client_sockaddr))) == -1){perror("bind");}server_sockaddr.sun_family = AF_UNIX;// 容易越界,本系统为108strncpy(server_sockaddr.sun_path, SOCK_PATH_S, sizeof(server_sockaddr.sun_path));printf("send message\n");// 向服务器发送信息,由server_sockaddr指定地址send_bytes = sendto(client_sockfd, send_buf, strlen(send_buf),0, (struct sockaddr *)&server_sockaddr, server_sockaddr_len);if (send_bytes == -1){perror("send");}if (send_bytes > 0){printf("%s\n", send_buf);}// 两个null是服务器的地址信息和长度,不需要则设为nullrecv_bytes = recvfrom(client_sockfd, recv_buf, sizeof(recv_buf),0, NULL, NULL);if (recv_bytes == -1){perror("recv");}if (recv_bytes > 0){printf("%s\n", recv_buf);}close(client_sockfd);printf("client close\n");// 用完必须删除文件unlink(SOCK_PATH_C);return 0;
}

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

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

相关文章

周末分享一篇关于html和http的文章吧

前面咱们说了https://blog.csdn.net/luohaitao/article/details/136974344&#xff08;说道说道JSP和HTTP吧-CSDN博客&#xff09;&#xff0c;把http的方法和jsp中httpservle对象的方法对上号了&#xff0c;其实从开发的角度看&#xff0c;jsp就是html中混入了java的服务端代码…

Rust并发编程thread多线程和channel消息传递

安全高效的处理并发是 Rust 诞生的目的之一&#xff0c;主要解决的是服务器高负载承受能力。 并发&#xff08;concurrent&#xff09;的概念是指程序不同的部分独立执行&#xff0c;这与并行&#xff08;parallel&#xff09;的概念容易混淆&#xff0c;并行强调的是"同…

DNS、DNS劫持与HTTPDNS:原理、应用与安全分析

文章目录 一、DNS原理和应用1.1 原理1.2 应用 二、DNS劫持的场景和原因分析2.1 场景2.2 原因分析 三、HTTPDNS的应用场景3.1 应用场景3.2 HTTPDNS服务商 四、总结 一、DNS原理和应用 DNS&#xff08;Domain Name System&#xff0c;域名系统&#xff09;是互联网的一项核心服务…

人工智能之Tensorflow批标准化

批标准化&#xff08;Batch Normalization,BN&#xff09;是为了克服神经网络层数加深导致难以训练而诞生的。 随着神经网络的深度加深&#xff0c;训练会越来越困难&#xff0c;收敛速度会很慢&#xff0c;常常会导致梯度消失问题。梯度消失问题是在神经网络中&#xff0c;当前…

chatgpt和 github copilot chat哪个更强

chatgpt大家应该都不陌生 ChatGPT 是由 OpenAI 开发的一种基于 GPT&#xff08;生成式预训练模型&#xff09;的聊天机器人。它可以生成语言上下文相关的响应&#xff0c;从而进行自然语言对话。ChatGPT 利用大规模的语言数据进行预训练&#xff0c;并通过微调或在线学习来适应…

【云开发笔记No.12】再说测试

一、自动化测试 自动化测试是软件开发过程中的重要环节&#xff0c;旨在通过自动化工具来执行测试用例&#xff0c;从而验证软件的功能、性能、安全性等方面是否符合预期。自动化测试能够显著提高测试效率&#xff0c;减少人为错误&#xff0c;并持续监控软件的质量。 关键技…

微服务(基础篇-002-Ribbon)

目录 Ribbon负载均衡&#xff08;1&#xff09; 负载均衡的原理&#xff08;1.1&#xff09; 负载均衡策略&#xff08;1.2&#xff09; Ribbon-IRule(1.2.1) 修改负载均衡的方法&#xff08;1.2.2&#xff09; 懒加载&#xff08;1.3&#xff09; 饥饿加载&#xff08;1…

ES聚合查询

ES聚合查询 {"query": {"bool": {"must": [{"terms": {"orderId": ["58880570952990","58882596943998","58880654706404"]}},{"term": {"billType": "110"}…

【Python操作基础】——for语句用法

&#x1f349;CSDN小墨&晓末:https://blog.csdn.net/jd1813346972 个人介绍: 研一&#xff5c;统计学&#xff5c;干货分享          擅长Python、Matlab、R等主流编程软件          累计十余项国家级比赛奖项&#xff0c;参与研究经费10w、40w级横向 文…

力扣74---搜索二维矩阵

目录 题目描述&#xff1a; 思路&#xff1a; 代码&#xff1a; 题目描述&#xff1a; 给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a; 每行中的整数从左到右按非严格递增顺序排列。 每行的第一个整数大于前一行的最后一个整数。 给你一个整数 targ…

mac 解决随机出现的蓝色框

macbookair为什么打字的时候按空格键会出现蓝色框? - 知乎

求任意数任何可能的乘方的个位数

形如该题&#xff1a;用到了循环节 1 2 4 8 6 3 9 7 1 4 6 5 6 7 9 3 1 8 4 2 6 9 1 如图为一到十的数字乘方的个位数的循环&#xff0c;可以看出有的数1个数一循环&#xff0c;有的是2个数一循环&#xff0c;有的是4个一循环。 例题&#xff1a; 则4肯定是所有所有个位数n次方…

前端学习笔记 | JS进阶

一、作用域 1、局部作用域 &#xff08;1&#xff09;函数作用域 &#xff08;2&#xff09;块作用域 let和const会产生块作用域 &#xff0c;而var不会产生块作用域 2、全局作用域 script标签和js文件的【最外层】变量 3、作用域链 本质&#xff1a;底层的变量查找机制 4、JS…

js 数组方法汇总(ES5数组方法,ES6新增的数组方法)

ES5,ES6数组方法汇总 ES5 数组方法&#xff1a;&#xff1a; concat()&#xff1a;合并多个数组为一个数组。 var array1 [1, 2, 3];var array2 [4, 5, 6];var newArray array1.concat(array2);console.log(newArray); // [1, 2, 3, 4, 5, 6]join()&#xff1a;将数组的所…

Docker(二):Docker常用命令

docker 查看docker支持的所有命令和参数。 ➜ ~ docker Management Commands:config Manage Docker configscontainer Manage containersimage Manage imagesnetwork Manage networksnode Manage Swarm nodesplugin Manage pluginssecret …

《手把手教你》系列技巧篇(四十九)-java+ selenium自动化测试-隐藏元素定位与操作(详解教程)

1.简介 对于前端隐藏元素&#xff0c;一直是selenium自动化定位元素的隐形杀手&#xff0c;脚本跑到隐藏元素时位置时报各种各样的错误&#xff0c;可是这种隐藏的下拉菜单又没有办法避免&#xff0c;所以非常头痛&#xff0c;这一篇只为交流隐藏元素自动化定位处理方法以及宏哥…

Docker进阶:Docker-cpmpose 实现服务弹性伸缩

Docker进阶&#xff1a;Docker-cpmpose 实现服务弹性伸缩 一、Docker Compose基础概念1.1 Docker Compose简介1.2 Docker Compose文件结构 二、弹性伸缩的原理和实现步骤2.1 弹性伸缩原理2.2 实现步骤 三、技术实践案例3.1 场景描述3.2 配置Docker Compose文件3.3 使用 docker-…

一文彻底搞懂MySQL索引

文章目录 1. 索引的优缺点2. 创建索引准则3. 索引的分类4. 索引实现5. 操作索引 1. 索引的优缺点 MySQL索引是一种数据结构&#xff0c;用于提高数据库查询效率。它可以快速定位到表中符合特定条件的数据行&#xff0c;从而加快查询速度。索引通常是根据表中的一个或多个字段创…

微软开源Garnet高性能缓存服务安装

Garnet介绍 Garnet是一款微软研究院基于C#开发而开源的高性能缓存服务&#xff0c;支持Windows、Linux多平台部署&#xff0c;Garnet兼容Redis服务API&#xff0c;在性能和使用架构上较Redis有很大提升&#xff08;官方说法&#xff09;&#xff0c;并提供与Redis一样的命令操…

Rust egui(3) 增加多个tab

话说不知道咋写&#xff0c;要不直接上git patch吧。代码都是移植的官方demo&#xff0c;核心改动就是把原来的line_demo换成了plot_demo&#xff0c;里面实现多个ui&#xff0c;然后点击tab标题会切换不同的ui。 如下图&#xff0c;Lines和Markers两个不同的标签对应不同的ui。…