day6_网络编程

网络聊天室

客户端

main.c

#include "include/errorAndHead.h"void hander(int sig)
{while (waitpid(-1, NULL, WNOHANG) > 0);
}int main(int argc, const char *argv[])
{/* 捕获 SIGCHLD 信号 hander 处理*/if (signal(SIGCHLD, hander) == SIG_ERR){ERR_MSG("socket");return -1;}msg Msg = {};Msg.type = 'L';strcpy(Msg.name, loginUI(Msg.name));// 创建客户端socketint cli_fd = socket(AF_INET, SOCK_DGRAM, 0);if (cli_fd < 0){ERR_MSG("socket");return -1;}struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(SER_PORT);          // 主机字节序转网络字节序sin.sin_addr.s_addr = inet_addr(SER_IP); // 点分十进制转网络字节序socklen_t sin_len = sizeof(sin);/* 该进程只服务的用户名 *//*  char name[20] = "";strcpy(name, Msg.name); */// 将聊天用户的基本信息发送给服务器if (sendto(cli_fd, &Msg, sizeof(Msg), 0, (struct sockaddr *)&sin, sizeof(sin)) < 0){ERR_MSG("sendto");return -1;}// 创建子进程pid_t pid = fork();if (pid == 0){char name[20] = "";strcpy(name, Msg.name);// 子进程while (1){memset(&Msg, 0, sizeof(Msg));fgets(Msg.text, sizeof(Msg.text), stdin);Msg.text[strlen(Msg.text) - 1] = 0;if (strcmp(Msg.text, "quit") == 0){/* 如果输入的是quit那么 通知下线 并且退出进程,并通知父进程死亡 */exit_chat(cli_fd, Msg, name, sin);kill(getppid(), SIGKILL);break;}msg_chat(cli_fd, Msg, name, sin);}exit(EXIT_SUCCESS);}else if (pid > 0){// 父进程用来接收数据while (1){memset(&Msg, 0, sizeof(Msg));if (recvfrom(cli_fd, &Msg, sizeof(Msg), 0, NULL, NULL) < 0){ERR_MSG("recvfrom");return -1;}switch (Msg.type){case 'L':// printf("system msg : %s\n", Msg.text);rec_login(Msg);break;case 'Q':// printf("system msg : %s\n", Msg.text);quitc_login(Msg);break;case 'C':rec_chat(Msg);break;default:break;}}exit(EXIT_SUCCESS);}close(cli_fd);return 0;
}

函数库

#include "include/errorAndHead.h"char *loginUI(char *username)
{memset(username, 0, sizeof(username));char e;printf("————————欢迎来到多人聊天室————————\n");printf("键入ENTRE继续...\n");scanf("%c", &e);if (e != '\n'){exit(EXIT_SUCCESS);}printf("请输入姓名->>>");scanf("%s", username);return username;
}int rec_login(msg Msg)
{if (Msg.type == 'L'){printf("system msg : %s\n", Msg.text);}return 0;
}int exit_chat(int cli_fd, msg Msg, char *name, struct sockaddr_in sin)
{strcpy(Msg.name, name);Msg.type = 'Q';if (sendto(cli_fd, &Msg, sizeof(Msg), 0, (struct sockaddr *)&sin, sizeof(sin)) < 0){ERR_MSG("sendto");return -1;}return 0;
}int quitc_login(msg Msg)
{if (Msg.type == 'Q'){printf("system msg : %s\n", Msg.text);}return 0;
}int msg_chat(int cli_fd, msg Msg, char *name, struct sockaddr_in sin)
{strcpy(Msg.name, name);Msg.type = 'C';if (sendto(cli_fd, &Msg, sizeof(Msg), 0, (struct sockaddr *)&sin, sizeof(sin)) < 0){ERR_MSG("sendto");return -1;}return 0;
}int rec_chat(msg Msg)
{if (Msg.type == 'C'){printf("%s\n",Msg.text);}return 0;
}

服务器

main.c

#include "include/errorAndHead.h"void hander(int sig)
{while (waitpid(-1, NULL, WNOHANG) > 0);
}int main(int argc, const char *argv[])
{/* 捕获 SIGCHLD 信号 hander 处理*/if (signal(SIGCHLD, hander) == SIG_ERR){ERR_MSG("socket");return -1;}// 创建服务器socketint ser_fd = socket(AF_INET, SOCK_DGRAM, 0);if (ser_fd < 0){ERR_MSG("socket");return -1;}// 绑定IP和portstruct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(SER_PORT);sin.sin_addr.s_addr = inet_addr(SER_IP);if (bind(ser_fd, (struct sockaddr *)&sin, sizeof(sin)) != 0){ERR_MSG("bind");return -1;}// 创建进程int pid = fork();if (pid > 0){// 父进程, 接收消息user_linklist *head = (user_linklist *)malloc(sizeof(user_linklist));head->len = 0;head->next = NULL;// 发送方接收容器struct sockaddr_in rec_cin;socklen_t rec_cin_len = sizeof(rec_cin);msg Msg;while (1){memset(&Msg, 0, sizeof(Msg));if (recvfrom(ser_fd, &Msg, sizeof(Msg), 0, NULL,NULL) < 0){ERR_MSG("recvfrom");return -1;}switch (Msg.type){case 'L':rec_login(ser_fd, rec_cin, Msg, head);break;case 'Q':quit_login(ser_fd, rec_cin, Msg, head);break;case 'C':msg_chat(ser_fd, rec_cin, Msg, head);break;default:break;}}free(head);head = NULL;exit(EXIT_SUCCESS);}else if (pid == 0){// 终端获取文本exit(EXIT_SUCCESS);}close(ser_fd);return 0;
}

函数库

#include "include/recive.h"int rec_login(int ser_fd, struct sockaddr_in rec_cin, msg Msg, user_linklistPtr head)
{/* 自己的终端打印成功登录 */printf("成功登录---IP:%s PORT:%d 用户名:%s\n", inet_ntoa(rec_cin.sin_addr), ntohs(rec_cin.sin_port), Msg.name);Msg.type = 'L';strcpy(Msg.text, "");sprintf(Msg.text, "——————%s 成功上线——————\n", Msg.name);/* 成功登录后,向所有人发送某人成功 上线 */user_linklistPtr ptr = head;while (ptr->next != NULL){ptr = ptr->next;if (sendto(ser_fd, &Msg, sizeof(Msg), 0, (struct sockaddr *)&(ptr->data), sizeof(ptr->data)) < 0){ERR_MSG("sendto");return -1;}}// 将登录的用户放入内存user_linklist *node = (user_linklist *)malloc(sizeof(user_linklist));node->next = NULL;node->data = rec_cin;head->next = node;head->len++;return 0;
}int quit_login(int ser_fd, struct sockaddr_in rec_cin, msg Msg, user_linklistPtr head)
{printf("退出成功---IP:%s PORT:%d 用户名:%s\n", inet_ntoa(rec_cin.sin_addr), ntohs(rec_cin.sin_port), Msg.name);strcpy(Msg.text, "");sprintf(Msg.text, "——————%s 下线了——————\n", Msg.name);user_linklistPtr ptr = head;while (ptr->next != NULL){ptr = ptr->next;if (sendto(ser_fd, &Msg, sizeof(Msg), 0, (struct sockaddr *)&(ptr->data), sizeof(ptr->data)) < 0){ERR_MSG("sendto");return -1;}}/* 在链表中删除下线的用户 */// 后续优化不影响程序运行
}int msg_chat(int ser_fd, struct sockaddr_in rec_cin, msg Msg, user_linklistPtr head)
{if (Msg.type != 'C'){return 0;}user_linklistPtr ptr = head;while (ptr->next != NULL){ptr = ptr->next;if (sendto(ser_fd, &Msg, sizeof(Msg), 0, (struct sockaddr *)&(ptr->data), sizeof(ptr->data)) < 0){ERR_MSG("sendto");return -1;}}
}

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

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

相关文章

webpack5 (三)

webpack 高级配置 其实就是对 webpack 进行优化&#xff0c;让代码在编译/运行时性能更好 1. 提升开发体验 2. 提升打包构建速度 3. 减少代码体积 4. 优化代码运行性能 一、提升开发体验 sourcemap 在编译打包后所有的 css 和 js 都合并为了一个文件&#xff0c;并多了很多…

APS系统设计经验分享(时间推导II - 2023.09)

在前一篇关于APS系统设计分享文章(《APS系统设计经验分享(时间推导 - 2023.03)》)中&#xff0c;我们提到将会分享使用OptaPlanner作为规划引擎开发APS系统过程中&#xff0c;遇到的一些时间相关的设计建议与异常情况分析。后来一直忙于项目工作&#xff0c;直到现在才想起仍欠…

CC-TAIX01 HONEYWELL 霍尼韦尔连接工厂热智商远程监测系统

CC-TAIX01 HONEYWELL 霍尼韦尔连接工厂热智商远程监测系统 -霍尼韦尔宣布霍尼韦尔连接工厂热智商,一种基于云的远程监测系统,旨在监测和管理关键的热过程数据。这是霍尼韦尔资产绩效管理(APM)投资组合的一部分。 热智商是工业和商业热应用的远程监测解决方案。它将燃烧设备连…

Flink基础实操-计算单词出现次数

&#x1f947;&#x1f947;【大数据学习记录篇】-持续更新中~&#x1f947;&#x1f947; 个人主页&#xff1a;beixi 本文章收录于专栏&#xff08;点击传送&#xff09;&#xff1a;【大数据学习】 &#x1f493;&#x1f493;持续更新中&#xff0c;感谢各位前辈朋友们支持…

【云原生】容器编排工具Kubernetes

目录 一、 K8S介绍 官网地址&#xff1a; 1.1docker编排与k8s编排相比 1.2特性 1.3功能 二、K8S重要组件 2.1核心组件 &#xff08;1&#xff09;Kube-apiserver &#xff08;2&#xff09;Kube-controller-manager &#xff08;3&#xff09;Kube-scheduler &#x…

DevOps管理软件生命周期

整体的软件开发流程 PLAN&#xff1a;开发团队根据客户的目标制定开发计划 CODE&#xff1a;根据PLAN开始编码过程&#xff0c;需要将不同版本的代码存储在一个库中。GIT,SVN BUILD&#xff1a;编码完成后&#xff0c;需要将代码构建并且运行。MAVEN TEST&#xff1a;成功构建…

【性能优化】聊聊性能优化那些事

针对于互联网应用来说&#xff0c;性能优化其实就是一直需要做的事情&#xff0c;因为系统响应慢&#xff0c;是非常影响用户的体验&#xff0c;可能回造成用户流失。所以对于性能非常重要。最近正好接到一个性能优化的需求&#xff0c;需要对所负责的系统进行性能提升。目前接…

Windows环境下RabbitMQ下载安装

一、准备安装文件 1、下载Erlang 登录网站Downloads - Erlang/OTP&#xff0c;选择“Download Windows installer”&#xff0c;如下图所示&#xff1a; 弹出框中&#xff0c;选在下载保存地址&#xff0c;保存文件&#xff0c;如下图所示&#xff1a; 2、下载RabbitMQ 登录…

ElasticSearch简介

一、基本概念 1、Index&#xff08;索引&#xff09; 动词&#xff0c;相当于 MySQL 中的 insert&#xff1b; 名词&#xff0c;相当于 MySQL 中的 Database 2、Type&#xff08;类型&#xff09; 在 Index&#xff08;索引&#xff09;中&#xff0c;可以定义一个或多个类…

无需公网IP,在家SSH远程连接公司内网服务器「cpolar内网穿透」

文章目录 1. Linux CentOS安装cpolar2. 创建TCP隧道3. 随机地址公网远程连接4. 固定TCP地址5. 使用固定公网TCP地址SSH远程 本次教程我们来实现如何在外公网环境下&#xff0c;SSH远程连接家里/公司的Linux CentOS服务器&#xff0c;无需公网IP&#xff0c;也不需要设置路由器。…

unity tolua热更新框架教程(2)

Lua启动流程 增加脚本luamain&#xff0c;继承luaclient 建立第一个场景GameMain&#xff0c;在对象GameMain挂载脚本LuaMain&#xff0c;启动场景 看到打印&#xff0c;lua被成功加载 lua入口及调用堆栈 这里会执行main.lua文件的main函数 C#接口导出 在此处配置C#导出的代码 …

算法leetcode|75. 颜色分类(rust重拳出击)

文章目录 75. 颜色分类&#xff1a;样例 1&#xff1a;样例 2&#xff1a;提示&#xff1a; 分析&#xff1a;题解&#xff1a;rust&#xff1a;go&#xff1a;c&#xff1a;python&#xff1a;java&#xff1a; 75. 颜色分类&#xff1a; 给定一个包含红色、白色和蓝色、共 n…

js集成zTree实现树形结构菜单

官方文档:https://www.treejs.cn/v3/api.php 一、简单创建 zTree 演示 $.fn.zTree.init($("#tree"), setting, zTreeNodes) 的用法$.fn.zTree.init 概述[ 依赖 jquery.ztree.core 核心 js ] zTree 初始化方法,创建 zTree 必须使用此方法 1、页面需要进行 W3C 申明…

【Python】爬虫练习-爬取豆瓣网电影评论用户的观影习惯数据

目录 前言 一、配置环境 1.1、 安装Python 1.2、 安装Requests库和BeautifulSoup库 1.3.、安装Matplotlib 二、登录豆瓣网&#xff08;重点&#xff09; 2.1、获取代理 2.2、测试代理ip是否可用 2.3、设置大量请求头随机使用 2.4、登录豆瓣网 三、爬取某一部热门电影…

SQLserver基础入门理论(超基础)二

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a; 小刘主页 ♥️努力不一定有回报&#xff0c;但一定会有收获加油&#xff01;一起努力&#xff0c;共赴美好人生&#xff01; ♥️学习两年总结出的运维经验&#xff0c;以及思科模拟器全套网络实验教程。专栏&#xf…

leetcode第361场周赛补题

7020. 统计对称整数的数目 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a;转化为字符串后枚举 class Solution { public:int countSymmetricIntegers(int low, int high) {int res 0;for(int i low; i < high; i ){string s to_string(i);if(s.size() % 2) …

【51单片机实验笔记】声学篇(一) 蜂鸣器基本控制

目录 前言硬件介绍PWM基础蜂鸣器简介 原理图分析蜂鸣器驱动电路 软件实现蜂鸣器短鸣蜂鸣器功能封装 总结 前言 蜂鸣器在生活中的应用实则相当广泛。通过本章你将学会制造噪声 &#xff08;笑~&#xff09;你将学会驱动它们&#xff0c;并发出响声。 硬件介绍 PWM基础 占空比…

shell bash中设置命令set

1 Preface/Foreword set命令用于shell脚本在执行命令时候&#xff0c;遇到异常的处理机制。 2 Usage 2.1 set -e 当执行命令过程中遇到异常&#xff0c;那么就退出脚本&#xff0c;不会往下执行其它命令。 #!/bin/bash #set -eroot GIT_TAG${CI_BUILD_TAG-NOTAG} GIT_REV…

设计模式之建造者模式与原型模式

目录 建造者模式 简介 使用场景 优缺点 模式结构 实现 原型模式 简介 应用场景 优缺点 模式结构 实现 建造者模式 简介 将复杂对象的构建与表示进行分离&#xff0c;使得同样的构建过程可以创建不同的表示。是一个将复杂的对象分解为多个简单的对象&#xff0c;然…

Uboot指令与烧录

目录 1 NAND Flash&#xff1a; 1&#xff09;地址空间说明 2&#xff09;烧写u-boot 3&#xff09;烧写内核 4&#xff09;烧写文件系统 5&#xff09;设置启动参数 2 SPI Flash&#xff1a; 1&#xff09;地址空间说明 2&#xff09;烧写u-boot 3&#xff09;烧写内…