当前位置: 首页 > news >正文

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

相关文章:

  • 全局UI方法-弹窗六-自定义弹窗
  • Flask 与小程序 的图片数据交互 过程及探讨研究学习
  • 如何在群晖NAS搭建bitwarden密码管理软件并实现无公网IP远程访问
  • Install Docker
  • 【机器学习】代价函数
  • #Linux(make工具和makefile文件以及makefile语法)
  • spark: 从pulsar中读取数据
  • tcpdump 抓包
  • 基于STELLA系统动态模拟技术及在农业、生态及环境科学中的应用教程
  • WINDOWS设置代理链chain
  • 一文整合工厂模式、模板模式、策略模式
  • 什么是通配符SSL证书?
  • Webgl学习系列-认识Webgl
  • 一、TLE9471 - SBC Mode切换 + VCC2 开关
  • 百度谷歌301强引蜘蛛池效果怎么样
  • JavaScript 如何正确处理 Unicode 编码问题!
  • 【402天】跃迁之路——程序员高效学习方法论探索系列(实验阶段159-2018.03.14)...
  • CSS选择器——伪元素选择器之处理父元素高度及外边距溢出
  • JSDuck 与 AngularJS 融合技巧
  • Spring Boot MyBatis配置多种数据库
  • uva 10370 Above Average
  • vue-cli在webpack的配置文件探究
  • 阿里云Kubernetes容器服务上体验Knative
  • 短视频宝贝=慢?阿里巴巴工程师这样秒开短视频
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 京东美团研发面经
  • 浅谈JavaScript的面向对象和它的封装、继承、多态
  • 如何编写一个可升级的智能合约
  • 如何进阶一名有竞争力的程序员?
  • 如何正确配置 Ubuntu 14.04 服务器?
  • 使用 Node.js 的 nodemailer 模块发送邮件(支持 QQ、163 等、支持附件)
  • 无服务器化是企业 IT 架构的未来吗?
  • 正则学习笔记
  • Mac 上flink的安装与启动
  • 完善智慧办公建设,小熊U租获京东数千万元A+轮融资 ...
  • ​Distil-Whisper:比Whisper快6倍,体积小50%的语音识别模型
  • #微信小程序:微信小程序常见的配置传旨
  • $.each()与$(selector).each()
  • (02)Hive SQL编译成MapReduce任务的过程
  • (2)关于RabbitMq 的 Topic Exchange 主题交换机
  • (20050108)又读《平凡的世界》
  • (Redis使用系列) Springboot 在redis中使用BloomFilter布隆过滤器机制 六
  • (附源码)springboot 校园学生兼职系统 毕业设计 742122
  • (力扣题库)跳跃游戏II(c++)
  • (全注解开发)学习Spring-MVC的第三天
  • (三)Pytorch快速搭建卷积神经网络模型实现手写数字识别(代码+详细注解)
  • .\OBJ\test1.axf: Error: L6230W: Ignoring --entry command. Cannot find argumen 'Reset_Handler'
  • .bashrc在哪里,alias妙用
  • .bat批处理(二):%0 %1——给批处理脚本传递参数
  • .NET MVC、 WebAPI、 WebService【ws】、NVVM、WCF、Remoting
  • .net 程序发生了一个不可捕获的异常
  • .Net 知识杂记
  • .NET分布式缓存Memcached从入门到实战
  • .NET学习全景图
  • @Transactional 详解