基于UDP实现直播间聊天的功能
需求:软件划分为用户客户端和主播服务端两个软件client.c和server.c 用户客户端负责:1.接收用户的昵称2.接收用户输入的信息,能够将信息发送给服务端3.接收服务端回复的数据信息,并完成显示主播服务端负责:1.对所有加入直播间的用户的IP地址和端口实现管理(加入、退出)2.当有新的客户端加入时,能够向所有客户端提示:"欢迎 XXX 用户进入直播间"3.当有客户端退出时,能够向所有客户端提示:"XXX 离开直播间"4.能够实现客户端聊天内容的转发,当某个客户端发送聊天信息时,能够将该信息转给除了该用户之外聊天室内所有其余客户端用户
head.h文件
#ifndef __HEAD_H__
#define __HEAD_H__#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <time.h>
#include <pwd.h>
#include <grp.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <netinet/in.h>struct address
{int mark;struct sockaddr_in addr;
};struct msgbuf{int type;char name[32];char text[512];
};#define MSG_TYPE_START 100
#define MSG_TYPE_END 200
#define MSG_TYPE_CHAT 300
#define RECV_ADDR "192.168.1.152"
#define RECV_PORT 50000#endif
client.c
#include "head.h"char name[32] = {0};
int sockfd = 0;
struct sockaddr_in recvaddr;
pthread_t tid_send; //发线程
pthread_t tid_recv; //收线程void *sendfun(void *arg)
{struct msgbuf sendmsg; ssize_t nsize = 0;while (1){memset(&sendmsg, 0, sizeof(sendmsg));sendmsg.type = MSG_TYPE_CHAT;sprintf(sendmsg.name, "%s", name);gets(sendmsg.text);if (!strcmp(sendmsg.text, ".quit")){sendmsg.type = MSG_TYPE_END;}nsize = sendto(sockfd, &sendmsg, sizeof(sendmsg), 0, (struct sockaddr *)&recvaddr, sizeof(recvaddr));if (-1 == nsize){perror("fail to sendto");return NULL;}if (sendmsg.type == MSG_TYPE_END){break;}}pthread_cancel(tid_recv);return NULL;
}void *recvfun(void *arg)
{struct msgbuf recvmsg;ssize_t nsize = 0;while (1){memset(&recvmsg, 0, sizeof(recvmsg));nsize = recvfrom(sockfd, &recvmsg, sizeof(recvmsg), 0, NULL, NULL);if (-1 == nsize){perror("fail to recvfrom");return NULL;}if (recvmsg.type == MSG_TYPE_CHAT){printf("%s(%s:%d)>%s\n", recvmsg.name, RECV_ADDR, RECV_PORT, recvmsg.text);}else if (recvmsg.type == MSG_TYPE_END){break;}}pthread_cancel(tid_send);return NULL;
}int main(void)
{struct msgbuf sendmsg;ssize_t nsize = 0;recvaddr.sin_family = AF_INET;recvaddr.sin_port = htons(RECV_PORT);recvaddr.sin_addr.s_addr = inet_addr(RECV_ADDR);printf("请输入您的昵称:\n");gets(name);sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (-1 == sockfd){perror("fail to socket");return -1;}memset(&sendmsg, 0, sizeof(sendmsg));sendmsg.type = MSG_TYPE_START;sprintf(sendmsg.name, "%s", name);nsize = sendto(sockfd, &sendmsg, sizeof(sendmsg), 0, (struct sockaddr *)&recvaddr, sizeof(recvaddr));if (-1 == nsize){perror("fail to sendto");return -1;}pthread_create(&tid_send, NULL, sendfun, NULL);pthread_create(&tid_recv, NULL, recvfun, NULL);pthread_join(tid_send, NULL);pthread_join(tid_recv, NULL);close(sockfd);return 0;
}
server.c
#include "head.h"struct address ClientIpList[100];int AddClientIp(struct sockaddr_in TmpAddr)
{int i = 0;for(i = 0;i < 100;++i){if(ClientIpList[i].mark == 0){ClientIpList[i].addr = TmpAddr;ClientIpList[i].mark = 1;break;}}return 0;
}
int DelClientIp(struct sockaddr_in TmpAddr)
{int i = 0;for(i = 0;i < 100;++i){if(0 == memcmp(&TmpAddr,&ClientIpList[i].addr,sizeof(TmpAddr))){ClientIpList[i].mark = 0;break;}}return 0;
}int BoardcastClientIp(int sockfd,struct sockaddr_in TmpAddr,struct msgbuf TmpMes)
{int i = 0;ssize_t nsize = 0;for(i = 0;i < 100;++i){if(ClientIpList[i].mark == 0){continue;}if(0 != memcmp(&TmpAddr,&ClientIpList[i].addr,sizeof(TmpAddr))){nsize = sendto(sockfd,&TmpMes,sizeof(TmpMes),0,(struct sockaddr *)&ClientIpList[i].addr,sizeof(ClientIpList[i].addr));if(-1 == nsize){continue;}}}return 0;
}int main(void)
{int sockfd = 0;int ret = 0;ssize_t nsize = 0;struct msgbuf recvmes;struct sockaddr_in recvaddr;struct sockaddr_in sendaddr;socklen_t addrlen = sizeof(sendaddr);recvaddr.sin_family = AF_INET;recvaddr.sin_port = htons(RECV_PORT);recvaddr.sin_addr.s_addr = INADDR_ANY;sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (-1 == sockfd){perror("fail to socket");return -1;}ret = bind(sockfd, (struct sockaddr *)&recvaddr, sizeof(recvaddr));if (-1 == ret){perror("fail to bind");return -1;}memset(&ClientIpList,0,sizeof(ClientIpList));while (1){memset(&recvmes, 0, sizeof(recvmes));nsize = recvfrom(sockfd, &recvmes, sizeof(recvmes), 0,(struct sockaddr *)&sendaddr, &addrlen);if (-1 == nsize){perror("fail to recvfrom");return -1;}if(recvmes.type == MSG_TYPE_START){AddClientIp(sendaddr);recvmes.type = MSG_TYPE_CHAT;sprintf(recvmes.text,"%s",recvmes.name);}else if (recvmes.type == MSG_TYPE_END){DelClientIp(sendaddr);recvmes.type = MSG_TYPE_CHAT;sprintf(recvmes.text,"%s",recvmes.name);}if (recvmes.type == MSG_TYPE_CHAT){BoardcastClientIp(sockfd,sendaddr,recvmes);}}close(sockfd);return 0;
}
结果:

相关文章:
基于UDP实现直播间聊天的功能
需求:软件划分为用户客户端和主播服务端两个软件client.c和server.c 用户客户端负责:1.接收用户的昵称2.接收用户输入的信息,能够将信息发送给服务端3.接收服务端回复的数据信息,并完成显示主播服务端负责:1.对所有加入直播间的用…...
html5cssjs代码 006 文章排版《桃花源记》
html5&css&js代码 006 文章排版《桃花源记》 一、代码二、解释页面整体结构:头部信息:CSS样式:文章内容: 这段代码定义了一个网页,用于展示文章《桃花源记》的内容。网页使用了CSS样式来定义各个部分的显示效果…...
勾八头歌之数据科学导论—数据采集实战
一、数据科学导论——数据采集基本概念 第1关:巧妇难为无米之炊 第2关:数据采集概念与内涵 二、数据科学导论——数据采集实战 第1关:单网页爬取 import urllib.request import csv import re# ********** Begin ********** # dataurllib.r…...
微信小程序云开发教程——墨刀原型工具入门(素材面板)
引言 作为一个小白,小北要怎么在短时间内快速学会微信小程序原型设计? “时间紧,任务重”,这意味着学习时必须把握微信小程序原型设计中的重点、难点,而非面面俱到。 要在短时间内理解、掌握一个工具的使用…...
C#与WPF通用类库
个人集成封装,仓库已公开 NetHelper 集成了一些常用的方法; 如通用的缓存静态操作类、常用的Wpf的ValueConverters、内置的委托类型、通用的反射加载dll操作类、Wpf的ViewModel、Command、Navigation、Messenger、部分常用UserControls(可绑定的Passwo…...
http协议中的强缓存与协商缓存,带图详解
此篇抽自本人之前的文章:http面试题整理 。 别急着跳转,先把缓存知识学会了~ http中的缓存分为两种:强缓存、协商缓存。 强缓存 响应头中的 status 是 200,相关字段有expires(http1.0),cache-control&…...
蓝桥杯2019年第十届省赛真题-修改数组
查重类题目,想到用标记数组记录是否出现过 但是最坏情况下可能会从头找到小尾巴,时间复杂度O(n2),数据范围106显然超时 再细看下题目,我们重复进行了寻找是否出现过,干脆把每个元素出现过的次数k记录下来,直…...
【Python使用】python高级进阶知识md总结第3篇:静态Web服务器-返回指定页面数据,静态Web服务器-多任务版【附代码文档】
python高级进阶全知识知识笔记总结完整教程(附代码资料)主要内容讲述:操作系统,虚拟机软件,Ubuntu操作系统,Linux内核及发行版,查看目录命令,切换目录命令,绝对路径和相对…...
ELK 日志分析系统
ELK (Elasticsearch、Logstash、Kibana)日志分析系统的好处是可以集中查看所有服务器日志,减轻了工作量,从安全性的角度来看,这种集中日志管理可以有效查询以及跟踪服务器被攻击的行为。 Elasticsearch 是个开源分布式…...
机器学习模型—逻辑回归
机器学习模型—逻辑回归 逻辑回归是一种用于分类任务的监督机器学习算法,其目标是预测实例属于给定类别的概率。逻辑回归是一种分析两个数据因素之间关系的统计算法。本文探讨了逻辑回归的基础知识、类型和实现。 什么是逻辑回归 逻辑回归用于二元分类,其中我们使用sigmoi…...
Ubuntu20.04 创建新的用户
1、了解Linux目录结构 推荐看一下:https://www.runoob.com/linux/linux-system-contents.html Linux支持多个用户进行操作的,这样提高了系统的安全性,也可以多人共用一个系统,不过要注意的是系统中安装的软件相关路径࿰…...
大数据入门之hadoop学习
大数据 1. 学习hadoop之前,我们先了解一下什么是大数据? 大数据通常指的是数据集规模非常庞大且难以在常规数据库和数据处理工具中有效处理的数据。 大数据的特点: 容量:大数据具有庞大的规模,远远超出了传统数据库和…...
MySQL安装使用(mac、windows)
目录 macOS环境 一、下载MySQL 二、环境变量 三、启动 MySql 四、初始化密码设置 windows环境 一、下载 二、 环境配置 三、安装mysql 1.初始化mysql 2.安装Mysql服务 3.更改密码 四、检验 1.查看默认安装的数据库 2.其他操作 macOS环境 一、下载MySQL 打开 MyS…...
Day27:安全开发-PHP应用TP框架路由访问对象操作内置过滤绕过核心漏洞
目录 TP框架-开发-配置架构&路由&MVC模型 TP框架-安全-不安全写法&版本过滤绕过 思维导图 PHP知识点 功能:新闻列表,会员中心,资源下载,留言版,后台模块,模版引用,框架开发等 技…...
c++: 引用能否替代指针? 详解引用与指针的区别.
文章目录 前言1. 引用和指针的最大区别:引用不能改变指向2. 引用和指针在底层上面是一样的3. 引用和指针在sizeof面前大小不同4. 有多级指针,没有多级引用5.引用是引用的实体,指针会向后偏移同一个类型的大小 总结 前言 新来的小伙伴如果不知道引用是什么?可以看我的上一篇文…...
Java项目源码基于springboot的家政服务平台的设计与实现
大家好我是程序员阿存,在java圈的辛苦码农。辛辛苦苦板砖,今天要和大家聊的是一款Java项目源码基于springboot的家政服务平台的设计与实现,项目源码以及部署相关请联系存哥,文末附上联系信息 。 项目源码:Java基于spr…...
十大排序算法(冒泡排序、插入排序、选择排序、希尔排序、堆排序、快排、归并排序、桶排序、计数排序、基数排序)
目录 一、冒泡排序: 二、插入排序: 三、选择排序: 四、希尔排序: 五、堆排序: 六、快速排序: 6.1挖坑法: 6.2左右指针法 6.3前后指针法: 七、归并排序: 八、桶…...
matplotlib 画多子图的时候添加图例/legend
一开始搞不懂图例是什么意思,以为是整个图,最后发现原来图例就是代码中的legend: 子图的图例(legend)用于解释图表中各条线、点或其他元素所代表的含义。图例通常位于图表的一角,以帮助观众理解图表中展示的…...
手写一个线程池
自己手动写一个线程池的必要条件需要先了解我们使用的线程池的功能。为什么会有线程池?这是为了减少线程创建和销毁的开销。复用线程的目的。为了达到这个目的。预计方案是:需要一个存放任务的队列,主线程相当于生产者,在这个队列…...
Spring Boot 多环境配置
Spring Boot 多环境配置 在现代的软件开发中,通常需要将应用程序部署到不同的环境中,如开发环境、生产环境和测试环境等。每个环境可能需要不同的配置参数,例如数据库连接信息、日志级别等。在 Spring Boot 中,我们可以通过简单的…...
SDMatte Web前端性能优化:大图片上传与预览的流畅体验实现
SDMatte Web前端性能优化:大图片上传与预览的流畅体验实现 1. 引言:大图片处理的用户体验痛点 在图像处理类Web应用中,用户上传大尺寸图片时常常面临几个典型问题:上传速度慢、页面卡顿、预览效果差。以SDMatte这样的智能抠图工…...
从达克熊螺旋栈道看木质拼装玩具的魅力:为何老少皆宜的创意新宠?
开篇:一次愉快的拼装体验最近我入手了一款达克熊的螺旋栈道木质拼装玩具,原本只是抱着试试看的心态,没想到不仅家里小朋友爱不释手,连我这个"大朋友"也沉迷其中。这款玩具让我们全家度过了一个充满创意和欢笑的周末&…...
【数据库系统】数据库系统概论——第十四章 大数据管理
第十四章 大数据管理 文章目录 第十四章 大数据管理 14.1大数据概述 14.1.1什么是大数据 14.1.2大数据的特征 14.2大数据的应用 14.2.1感知现在 预测未来----互联网文本大数据管理与挖掘 14.2.2数据服务 实时推荐----基于大数据分析的用户建模 14.3大数据管理系统 14.3.1NoSQL数…...
pcl2启动器下载
PCL2(全称 Plain Craft Launcher 2,中文常称为 PCL2 启动器)是由国内知名开发者"龙腾猫跃"倾力打造的一款《我的世界》(Minecraft)第三方启动工具。 PCL2 启动器集成了众多游戏版本、Mod、整合包相关的内容…...
数据存储与管理:QmlBook本地存储与SQL集成教程
数据存储与管理:QmlBook本地存储与SQL集成教程 【免费下载链接】qmlbook The source code for the upcoming qml book 项目地址: https://gitcode.com/gh_mirrors/qm/qmlbook QmlBook提供了全面的本地存储解决方案,帮助开发者轻松实现应用数据的持…...
OpenClaw多模型混搭方案:Kimi-VL-A3B-Thinking与Qwen3-32B协同工作流
OpenClaw多模型混搭方案:Kimi-VL-A3B-Thinking与Qwen3-32B协同工作流 1. 为什么需要多模型混搭? 去年冬天,当我第一次尝试用OpenClaw处理图文混排的文档时,遇到了一个尴尬的问题:纯文本模型Qwen3-32B对图片内容视而不…...
查老板信息免费?3款工具深度功能对比(附避坑指南)
查老板信息免费的方法有很多,但大多数人都只停留在基础工商信息层面。真正能免费查到深度信息(关联企业、风险记录、AI解读)的工具其实不多,我最近亲测了几款常用工具,发现风鸟企业查询平台在免费深度功能方面表现突出…...
JavaScript中BigInt与Number类型混用的报错机制
JavaScript中BigInt与Number不能直接混合运算,会立即抛出TypeError;所有涉及两者混合的算术和关系操作(如1n1、10n<5)均报错,仅和不报错但返回false。JavaScript中BigInt与Number不能直接混合运算,会立即…...
【Dify企业级集成终极壁垒】:C# 14原生AOT部署实操手册——从IL解析到符号剥离,覆盖17个面试官追问点
第一章:C# 14原生AOT部署Dify客户端面试综述在现代AI工程化落地场景中,轻量、安全、低延迟的客户端集成能力日益关键。C# 14 引入的原生AOT(Ahead-of-Time)编译能力,结合 Dify 提供的标准化 REST API 与 OpenAPI 规范&…...
Arduboy光线投射渲染库:8位MCU上的实时3D引擎
1. ArduboyRaycast 库概述ArduboyRaycast 是一个专为 Arduboy 平台设计的轻量级光线投射(Raycasting)渲染库,面向资源极度受限的 8-bit AVR 微控制器(ATmega32U4,16MHz,2.5KB RAM,32KB Flash&am…...
