华清远见嵌入式学习——网络编程——小项目
项目要求:

代码实现:
服务器端:
#include <myhead.h>//定义协议包
struct proto
{char type;char name[20];char text[128];
};int main(int argc, const char *argv[])
{//判断从终端输入的字符串的个数if(argc != 3){printf("input error\n");printf("usage:./a.out 本机IP 本机端口\n");return -1;}//创建用于通信的套接字int sfd = socket(AF_INET,SOCK_DGRAM,0);if(sfd == -1){perror("socket error");return -1;}//设置端口号快速重用int reuse = 1;if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1){perror("setsockopt error");return -1;}//绑定服务器IP和端口号填充服务器地址信息结构体short port = (short)atoi(argv[2]);struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_addr.s_addr = inet_addr(argv[1]);sin.sin_port = htons(port);绑定if(bind(sfd,(struct sockaddr *)&sin,sizeof(sin)) == -1){perror("bind error");return -1;}//定义客户端地址信息结构体struct sockaddr_in cin;cin.sin_family = AF_INET;socklen_t socklen = sizeof(cin);//定义客户端地址信息结构体数组,用于存放多个客户端地址信息struct sockaddr_in savecin[1024];//初始化每个信息结构体内的第一个成员for(int i = 0;i < 1024;i++){savecin[i].sin_family = AF_INET;}定义一个用于检测文件描述符的集合fd_set readfds, tempfds; //在栈区定义清空容器中的内容FD_ZERO(&readfds);将要检测的文件描述符放入集合中FD_SET(sfd, &readfds); //将sfd文件描述符放入FD_SET(0, &readfds); //将0号文件描述符放入//对客户端的数据进行保存和转发char buf[256] = "";int res1,res2;int n = 0;//定义协议包结构体变量struct proto pro;struct proto send;while(1){bzero(buf,sizeof(buf));tempfds = readfds;使用select阻塞等待集合中的文件描述符有事件产生res1 = select(sfd+1, &tempfds, NULL, NULL, NULL);if(res1 == -1){perror("select error");return -1;}else if(res1 == 0){printf("time out\n");return -1;}//接收客户端信息if(FD_ISSET(sfd,&tempfds)){res2 = recvfrom(sfd,&pro,sizeof(pro),0,(struct sockaddr *)&cin,&socklen);if(res2 == -1){perror("recvfrom error");return -1;}//登录时存储客户端到数组中if(pro.type == 'L'){savecin[n] = cin;n++;sprintf(buf,"---%s已上线---",pro.name);printf("%s\n",buf);for(int i = 0;i < n;i++){if(savecin[i].sin_port == cin.sin_port){continue;} sendto(sfd,&pro,sizeof(pro),0,(struct sockaddr *)&savecin[i],sizeof(savecin[i]));}}if(pro.type == 'C'){//群聊send.type = pro.type;strcpy(send.name,pro.name);strcpy(send.text,pro.text);for(int i = 0;i < n;i++){if(savecin[i].sin_port == cin.sin_port){continue;} sendto(sfd,&send,sizeof(send),0,(struct sockaddr *)&savecin[i],sizeof(savecin[i]));}}if(pro.type == 'Q'){//下线send.type = pro.type;strcpy(send.name,pro.name);strcpy(send.text,pro.text);for(int i = 0;i < n;i++){bzero(buf,sizeof(buf));sprintf(buf,"---%s已下线---\n",send.name);printf("%s\n",buf);//删除该用户if(savecin[i].sin_port == cin.sin_port){int t = i;for(int j = i;j <= n;j++){savecin[t] = savecin[t+1];t++; }}n--;sendto(sfd,&send,sizeof(send),0,(struct sockaddr *)&savecin[i],sizeof(savecin[i]));}}}if(FD_ISSET(0,&tempfds)){bzero(send.name,sizeof(send.name));bzero(send.text,sizeof(send.text));send.type = 'C';strcpy(send.name,"系统消息");fgets(send.text,sizeof(send.text),stdin);send.text[strlen(send.text)-1] = '\0';for(int i = 0;i <= n;i++){sendto(sfd,&send,sizeof(send),0,(struct sockaddr *)&savecin[i],sizeof(savecin[i]));} }}//关闭套接字文件描述符close(sfd);return 0;
}
客户端:
#include <myhead.h>//定义协议包结构体
struct proto
{char type;char name[20];char text[128];
};int main(int argc, const char *argv[])
{//判断终端输入的字符串的个数if(argc != 3){printf("input error\n");printf("usage:./a.out 服务器IP 服务器端口号\n");return -1;}//创建用于通信的套接字int cfd = socket(AF_INET,SOCK_DGRAM,0);if(cfd == -1){perror("socket error");return -1;}//填充服务器地址信息结构体short port = (short)atoi(argv[2]); struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_addr.s_addr = inet_addr(argv[1]);sin.sin_port = htons(port);socklen_t socklen = sizeof(sin);//定义协议包结构体变量struct proto pro;//填充登录协议printf("请输入姓名>>");//登录pro.type = 'L'; fgets(pro.name,sizeof(pro.name),stdin);pro.name[strlen(pro.name)-1] = '\0';sendto(cfd,&pro,sizeof(pro),0,(struct sockaddr *)&sin,sizeof(sin));定义一个用于检测文件描述符的集合fd_set readfds, tempfds; //在栈区定义清空容器中的内容FD_ZERO(&readfds);将要检测的文件描述符放入集合中FD_SET(cfd, &readfds); //将sfd文件描述符放入FD_SET(0, &readfds); //将0号文件描述符放入//向服务器发送或从服务器接收消息char rbuf[128] = "";int res = 0;char name1[20] = "";strcpy(name1,pro.name);while(1){将集合内容复制一份tempfds = readfds;使用select阻塞等待集合中的文件描述符有事件产生res = select(cfd+1, &tempfds, NULL, NULL, NULL);if(res == -1){perror("select error");return -1;}else if(res == 0){printf("time out\n");return -1;}//群聊和退出if(FD_ISSET(0,&tempfds)){bzero(pro.text,sizeof(pro.text));//从终端获取内容fgets(pro.text,sizeof(pro.text),stdin);pro.text[strlen(pro.text)-1] = '\0';if(strcmp(pro.text,"quit") == 0){//退出pro.type = 'Q';sendto(cfd,&pro,sizeof(pro),0,(struct sockaddr *)&sin,sizeof(sin));//关闭套接字文件描述符close(cfd);break;}else{//群聊pro.type = 'C';sendto(cfd,&pro,sizeof(pro),0,(struct sockaddr *)&sin,sizeof(sin));}}//接收来自服务器的消息if(FD_ISSET(cfd,&tempfds)){bzero(rbuf,sizeof(rbuf));bzero(pro.text,sizeof(pro.text));res = recvfrom(cfd,&pro,sizeof(pro),0,NULL,NULL);if(res < 0){perror("recvfrom error");return -1;}if(pro.type == 'L'){printf("---%s已登录---\n",pro.name);}if(pro.type == 'C'){printf("%s:%s\n",pro.name,pro.text);if(strcmp(pro.name,"系统消息") == 0){strcpy(pro.name,name1);}}if(pro.type == 'Q'){printf("---%s已下线---\n",pro.name);}}}//关闭套接字文件描述符close(cfd);return 0;
}
代码运行效果图:

相关文章:
华清远见嵌入式学习——网络编程——小项目
项目要求: 代码实现: 服务器端: #include <myhead.h>//定义协议包 struct proto {char type;char name[20];char text[128]; };int main(int argc, const char *argv[]) {//判断从终端输入的字符串的个数if(argc ! 3){printf("…...
分库分表、分布式数据库、MPP
分库分表、分布式数据库、MPP的区别吗? 一、MySQL分库分表和MySQL分布式集群在性能方面各有优劣,具体取决于应用场景和需求。 MySQL分库分表: 在分库分表的场景下,可以将负载分散到多个数据库实例上,从而提高整体性能…...
浅学指针(2)数组函数传值调用
系列文章目录 文章目录 系列文章目录前言1. 指针的使⽤和传址调⽤结论:实参传递给形参的时候,形参会单独创建⼀份临时空间来接收实参,对形参的修改不影响实 参。那么这个时候,就要搬出指针大哥,在main函数中将a和b的地…...
C++之unordered_map/set的使用
前面我们已经学习了STL中底层为红黑树结构的一系列关联式容器——set/multiset 和 map/multimap(C98). unordered系列关联式容器 在C98中, STL提供了底层为红黑树结构的一系列关联式容器, 在查询时效率可达到log2N,即最差情况下需要比较红黑树的高度次, 当树中的节点非常多时,…...
docker打包chatpdf(自写)
docker打包上传 docker build -t kitelff/chatpdf:v0.1 .##修改镜像名字 docker tag c2c1a0eb4e08 kitelff/chatpdf:v0.1## push docker push kitelff/chatpdf:v0.1上传文件,测试效果...
shell基础
一.Shell脚本编程概述 1.基本概念 将要执行的命令按顺序保存到一个文本文件; 给该文件可执行权限; 可结合各种Shell控制语句以完成更复杂的操作。 2.作用 Linux系统中的Shell是一个特殊的应用程序,它介于操作系统内核与用户之间&#x…...
力扣1038. 从二叉搜索树到更大和树(java,树的中序遍历解法)
Problem: 1038. 从二叉搜索树到更大和树 文章目录 题目描述思路解题方法复杂度Code 题目描述 给定一个二叉搜索树 root (BST),请将它的每个节点的值替换成树中大于或者等于该节点值的所有节点值之和。 提醒一下, 二叉搜索树 满足下列约束条件ÿ…...
使用正则表达式来判断一个字符串只是否包含数字
使用正则表达式来判断一个字符串只是否包含数字 1、第一种 import java.util.regex.Pattern;public class Main {public static void main(String[] args) {String inputString "12345";if (containsOnlyDigits(inputString)) {System.out.println("字符串只…...
C#Wpf关于日志的相关功能扩展
目录 一、日志Sink(接收器) 二、Trace追踪实现日志 三、日志滚动 一、日志Sink(接收器) 安装NuGet包:Serilog Sink有很多种,这里介绍两种: Console接收器(安装Serilog.Sinks.Console); File接收器(安装…...
亚马逊云科技AI创新应用下的托管在AWS上的数据可视化工具—— Amazon QuickSight
目录 Amazon QuickSight简介 Amazon QuickSight的独特之处 Amazon QuickSight注册 Amazon QuickSight使用 Redshift和Amazon QuickSightt平台构建数据可视化应用程序 构建数据仓库 数据可视化 Amazon QuickSight简介 亚马逊QuickSight是一项可用于交付的云级商业智能 (BI…...
MySQL安全性:用户认证、防范SQL注入和SSL/TLS配置详解
MySQL作为广泛使用的关系型数据库管理系统,安全性至关重要。在本篇技术博客中,我们将深入探讨MySQL的用户认证方式、防范SQL注入攻击的方法以及SSL/TLS加密的配置。 1. MySQL用户认证方式 MySQL支持多种用户认证方式,其中两种常见方式是cac…...
EMG肌肉信号处理合集 (一)
本文归纳了常见的肌肉信号预处理流程,方便EMG信号的后续分析。使用pyemgpipeline库 来进行信号的处理。文中使用了 UC Irvine 数据库的下肢数据。 目录 1 使用wrappers 定义数据类,来进行后续的操作 2 肌电信号DC偏置去除 3 带通滤波器处理 4 对肌电…...
学自动化测试?我劝你还是算了吧。。。
本人7年测试经验,在学测试之前对电脑的认知也就只限于上个网,玩个办公软件。这里不能跑题,我为啥说:自学软件测试,一般人我还是劝你算了吧?因为我就是那个一般人! 软件测试基础真的很简单&…...
第一百七十八回 介绍一个三方包组件:SlideSwitch
文章目录 1. 概念介绍2. 使用方法3. 代码与效果3.1 示例代码3.2 运行效果 4. 内容总结 我们在上一章回中介绍了"如何创建垂直方向的Switch"相关的内容,本章回中将 介绍SlideSwitch组件.闲话休提,让我们一起Talk Flutter吧。 1. 概念介绍 我们…...
Windows任务管理器内存性能界面各个参数含义
任务管理器的内存性能界面提供了一些关键参数,这些参数可以帮助你了解系统中内存的使用情况。以下是一些常见的参数及其含义: 已提交(Committed): 表示已分配的物理内存和虚拟内存的总和。已提交的内存包括当前正在使…...
深度学习人脸表情识别算法 - opencv python 机器视觉 计算机竞赛
文章目录 0 前言1 技术介绍1.1 技术概括1.2 目前表情识别实现技术 2 实现效果3 深度学习表情识别实现过程3.1 网络架构3.2 数据3.3 实现流程3.4 部分实现代码 4 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 深度学习人脸表情识别系…...
全职RISC-V芯片D1开发板使用adb串口COM连接设备和文件上传下载
将两个USB端口都连接到工作电脑 推荐使用ADB工具访问开发板,下载连接如下: Windows版本:https://dl.google.com/android/repository/platform-tools-latest-windows.zip Mac版本:https://dl.google.com/android/repository/pla…...
STM32笔记---RTC
目录 一、RTC简介 二、主要特性 三、功能描述 3.1 读RTC寄存器 3.2 配置RTC寄存器 四、BKP简介 五、RTC_Init() 1. 函数BKP_ReadBackupRegister 2.RCC_LSEConfig设置外部低速晶振(LSE) 3.RTC基本结构 5.RTC_Init()实现 6.time.h 一、R…...
C语言之strstr函数的使用和模拟实现
C语言之strstr函数的模拟实现 文章目录 C语言之strstr函数的模拟实现1. strstr函数的介绍2. strstr函数的使用3. strstr的模拟实现3.1 实现思路3.2 实现代码 1. strstr函数的介绍 函数声明如下: char * strstr ( const char * str1, const char * str2 ); strs…...
【间歇振荡器2片555时基仿真】2022-9-24
缘由multisim出现这个应该怎么解决吖,急需解决-嵌入式-CSDN问答 输出一定要有电阻分压才能前后连接控制否则一定报错。...
【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...
Ray框架:分布式AI训练与调参实践
Ray框架:分布式AI训练与调参实践 系统化学习人工智能网站(收藏):https://www.captainbed.cn/flu 文章目录 Ray框架:分布式AI训练与调参实践摘要引言框架架构解析1. 核心组件设计2. 关键技术实现2.1 动态资源调度2.2 …...
LeetCode - 148. 排序链表
目录 题目 思路 基本情况检查 复杂度分析 执行示例 读者可能出的错误 正确的写法 题目 148. 排序链表 - 力扣(LeetCode) 思路 链表归并排序采用"分治"的策略,主要分为三个步骤: 分割:将链表从中间…...
LeetCode 2894.分类求和并作差
目录 题目: 题目描述: 题目链接: 思路: 思路一详解(遍历 判断): 思路二详解(数学规律/公式): 代码: Java思路一(遍历 判断&a…...
n8n:解锁自动化工作流的无限可能
在当今快节奏的数字时代,无论是企业还是个人,都渴望提高工作效率,减少重复性任务的繁琐操作。而 n8n,这个强大的开源自动化工具,就像一位智能的数字助手,悄然走进了许多人的工作和生活,成为提升…...
RMQ 算法详解(区间最值问题)
RMQ 算法详解(区间最值问题) 问题介绍解决方法暴力法ST表法基本思想算法步骤C实现 问题介绍 RMQ问题是OI中经常遇到的问题,主要是一下形式: 给你一堆数,不断的对里面的数进行操作,例如:让某个…...
2. Web网络基础 - 协议端口
深入解析协议端口与netstat命令:网络工程师的实战指南 在网络通信中,协议端口是服务访问的门户。本文将全面解析端口概念,并通过netstat命令实战演示如何监控网络连接状态。 一、协议端口核心知识解析 1. 端口号的本质与分类 端口范围类型说…...
