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

结果:

在这里插入图片描述

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

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

相关文章

网络协议栈--应用层--HTTPS协议

目录 一、HTTPS协议原理1.1 HTTPS协议是什么&#xff1f;1.2 概念准备1.2.1 什么是“加密”&#xff1f;1.2.2 为什么要加密&#xff1f;1.2.3 常见的加密方式1.2.3.1 对称加密1.2.3.2 非对称加密 1.2.4 数据摘要&&数据指纹1.2.5 数字签名1.2.6 理解链-承上启下 1.3 HT…

第十五章 构建和配置 Nginx 以与 Web 网关配合使用 (Windows) - 为 CSP 构建 Nginx 的过程

文章目录 第十五章 构建和配置 Nginx 以与 Web 网关配合使用 (Windows) - 为 CSP 构建 Nginx 的过程 第十五章 构建和配置 Nginx 以与 Web 网关配合使用 (Windows) - 为 CSP 构建 Nginx 的过程 在 MSYS2 shell 中工作&#xff0c;创建 Nginx 文档中建议的工作目录结构&#xf…

React-封装自定义Hook

1.声明函数 说明&#xff1a;声明一个以use打头的函数 function useToggle(){} 2.封装 说明&#xff1a;在函数体内封装可复用的逻辑 const [value,setValue]useState(true)const toggle()>{setValue(!value)} 3.返回 说明&#xff1a;把组件中用到的状态或者回调retu…

关于JVM的小总结(待补充)

JVM组成及他们之间的关系 装载类子系统字节码执行引擎运行时数据区 装载类子系统 类加载器字节码调节器类加载运行时数据区 字节码执行引擎 运行时数据区 线程私有 虚拟机栈本地方法栈程序计数器 线程共享 堆方法区&#xff08;元空间&#xff09;

后见之明!错过6个涨停板之后的复盘

在今年1月2日和1月3日&#xff0c;旅游板块两支个股先后涨停&#xff0c;此后一支月内三倍&#xff0c;另一支连续6个涨停。事后复盘&#xff0c;我们如何在1月2日第一支个股涨停之后&#xff0c;通过量化分析&#xff0c;找出第二支股&#xff1f; 一个3倍&#xff0c;一个6连…

Java 包和 API 深度解析:组织代码,避免命名冲突

Java 包和 API Java 中的包 用于将相关的类分组在一起。可以将其视为文件目录中的一个文件夹。我们使用包来避免名称冲突&#xff0c;并编写更易于维护的代码。 包分为两类: 内置包&#xff08;来自 Java API 的包&#xff09;用户定义的包&#xff08;创建自己的包&#xf…

维修ESA 数控折弯机CNC S 530 系统工控屏 S525 工业电脑显示屏

了解数控机床的组件可以帮助您充分利用该设备。 了解各种机器零件是有意义的&#xff0c;因为制造业的这些主力随处可见。 CNC 系统只会越来越受欢迎。 到2030年&#xff0c;美国数控机床市场规模将达到40亿美元。 我们首先回顾一下数控机床的定义及其优点。 然后我们将识别每…

根据全量知识系统内容规划-百度文库AI应用中心给出的答复

以下是就前面的文章&#xff08;全量知识系统的完整设计考虑和规划 之序 内容规划&#xff09;&#xff0c;和百度文库AI应用中心的答问。 全量知识系统的完整设计考虑和规划 之序 内容规划-CSDN博客 答问 Q1~6. 请对我以上设计规划&#xff0c;作出分析和完善&#xff0c;并…

M1电脑 Xcode15升级遇到的问题

遇到四个问题 一、模拟器下载经常报错。 二、Xcode15报错: SDK does not contain libarclite 三、报错coreAudioTypes not found 四、xcode模拟器运行一次下次必定死机 一、模拟器下载经常报错。 可以https://developer.apple.com/download/all/?qios 下载最新的模拟器&…

线程使用Runnable还是Callable

Callable接口 Runnable的缺陷 在创建线程的时候不管是继承Thread类(Thread本身也是实现的Runnable接口)还是实现Runnable接口&#xff0c;所实现的run()方法都没有返回值&#xff0c;使得需要将返回值写到map中&#xff0c;等到线程结束再去从map中取数据&#xff0c;特别的不方…

网站被插入虚假恶意链接怎么办?

在当前的电信和网络环境中&#xff0c;诈骗案件频发&#xff0c;许多受害者不幸上当&#xff0c;主要原因是他们点击了诈骗者发送的假链接。这些诈骗网站经常模仿真实网站的外观&#xff0c;使人难以分辨真伪。那么&#xff0c;我们应如何鉴别这些诈骗链接呢&#xff1f; 下面…

多个数据库驱动并存情况下无法找到数据库驱动问题解决

最近在打fat-jar包时&#xff0c;出现一个问题&#xff0c;运行fat-jar时报错&#xff1a; 2024-03-08 10:08:08.772 WARN [Thread-5] c.k.s.f.ExternalFuncClassLoader : 创建了未包含任何路径的自定义类加载器实例 2024-03-08 10:08:08.781 INFO [Thread-5] c.k.…

leetcode 2834.找出美丽数组的最小和

这道题作者一开始用的暴力解法&#xff0c;效果还不错&#xff0c;但是对于特别大的数据是过不去的。 先讲一下我暴力的思路&#xff1a;作者用了双指针的解法&#xff0c;我们可以先定义一个数组&#xff0c;就是把数组从1开始考虑&#xff0c;n个连续整数输入到里面去。 然…

工业制氧机的使用与维护管理指南

工业制氧机是工业生产中不可或缺的重要设备&#xff0c;其高效稳定的供氧功能对于保障生产过程的顺利进行至关重要。为了确保工业制氧机能够持续高效地提供氧气&#xff0c;正确的使用方法和维护措施是必不可少的。 在使用工业制氧机时&#xff0c;我们首先要确保设备放置在通风…

网络聊天室的UDP实现以及数据库

网络聊天室UDP实现 服务器端&#xff1a; 头文件&#xff1a; #include <myhead.h>//定义客户信息结构体 typedef struct magtye {char type; //消息类型char name[100]; //客户姓名char text[1024]; //客户发送聊天信息 }msg_t;//定义结构体存储…

mysql的语法总结2

命令&#xff1a; mysql -u 用户名 -p mysql登录 命令&#xff1a;create database u1 创建数据库u1 查询数据库 使用数据库u1 创建表department 查询表department ALTER TABLE 表名 操作类型&#xff1b; 操作类型可以有以下的操作&#xff1a; 添加列&#x…

ZCC3808 低静态电流、可编程延迟监控电路 替代TPS3808

1 特性 • 上电复位发生器具有可调节延迟时间&#xff1a;1.25ms 至10s • 超低静态电流&#xff1a;2.4μA&#xff08;典型值&#xff09; • 高阈值精度&#xff1a;0.5% 典型值 • 提供适用于标准电压轨的 0.9V 至 5V 固定阈值电压且可调节电压低至 0.4V • 手动复位 …

CubeMX使用教程(2)——点亮LED

在上一章&#xff0c;我们完成了CubeMX的环境配置&#xff0c;这一章我们通过CubeMX来完成点亮LED的工作。 通过LED原理图可知&#xff0c;如果我们要点亮LD1&#xff08;第一个灯&#xff09;&#xff0c;它对应开发板的PC8端口&#xff0c;因此我们应该在CubeMX中将PC8配置为…

【并查集】一种简单而强大高效的数据结构

目录 一、并查集原理 二、并查集实现 三、并查集应用 1. LeetCode并查集相关OJ题 2. 并查集的其他应用及总结 一、并查集原理 并查集&#xff08;Disjoint Set&#xff09;是一种用来管理元素分组和查找元素所属组别的数据结构。它主要支持两种操作&#xff1a;查找&…

公司内部的手机拍照管理办法建议

公司内部的手机拍照管理是一项重要的工作&#xff0c;因为它涉及到公司的信息安全、知识产权保护和隐私保护等方面。以下是一些建议的公司内部手机拍照管理办法&#xff1a; 明确拍照目的和范围&#xff1a;首先&#xff0c;公司应明确员工使用手机拍照的目的和范围。例如&…