9.7(UDP局域网多客户端聊天室)

2024-09-08 03:52

本文主要是介绍9.7(UDP局域网多客户端聊天室),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

服务器端

#include<myhead.h>
#define SERIP "192.168.0.132"
#define SERPORT 8888
#define MAX 50
//定义用户结构体
typedef struct{struct sockaddr_in addr;int flag;
}User;User users[MAX];//用户列表void add_user(struct sockaddr_in *client){// 检查用户是否已经在列表中for (int i = 0; i < MAX; i++) {if (users[i].flag == 1 && memcmp(&users[i].addr, client, sizeof(struct sockaddr_in)) == 0) {// 用户已经在列表中return;}}for(int i=0;i<MAX;i++){if(users[i].flag==0){users[i].addr = *client;users[i].flag = 1;break;}}
}//向用户转发消息,排除发送者
void transform(char *buff,struct sockaddr_in *send,int oldfd){for(int i=0;i<MAX;i++){if(users[i].flag!=0){if(memcmp(&users[i].addr,send,sizeof(struct sockaddr_in))!=0){sendto(oldfd,buff,strlen(buff),0,(struct sockaddr *)&users[i].addr,sizeof(users[i].addr));}}}}int main (int argc, const char *argv[])
{//定义套接字int oldfd = socket(AF_INET,SOCK_DGRAM,0);if(oldfd==-1){perror("oldfd");return -1;}int kkk=2; if(setsockopt(oldfd,SOL_SOCKET,SO_BROADCAST,&kkk,sizeof(kkk))==-1){ perror("setsockopt"); return -1;} //绑定端口struct sockaddr_in server = {.sin_family = AF_INET,.sin_addr.s_addr = inet_addr(SERIP),.sin_port = htons(SERPORT)};int server_len = sizeof(server);if(bind(oldfd,(struct sockaddr *)&server,server_len)==-1){perror("bind");return -1;}printf("UDP聊天服务器启动,端口号为:%d\n",SERPORT);//IO多路复用struct pollfd fds[1];fds[0].fd = oldfd;fds[0].events = POLLIN;char buff[1024];struct sockaddr_in client;int client_len = sizeof(client);while(1){int poll_count = poll(fds,1,-1);if(fds[0].revents == POLLIN){memset(buff,0,sizeof(buff));int len = recvfrom(oldfd,buff,sizeof(buff),0,(struct sockaddr *)&client,&client_len);if(len == 0){perror("recvfrom");return -1;}buff[len] = '\0';printf("接收到来自%s:%d的消息%s\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port),buff);//添加用户到列表add_user(&client);//转发给其他用户transform(buff,&client,oldfd);}}close(oldfd);return 0;
}

客户端

#include<myhead.h>
#define SERIP "192.168.0.132"
#define SERPORT 8888
#define MAX 50int main (int argc, const char *argv[])
{//创建套接字int oldfd = socket(AF_INET,SOCK_DGRAM,0);if(oldfd==-1){perror("oldfd");return -1;}struct sockaddr_in server={.sin_family = AF_INET,.sin_port = htons(SERPORT),.sin_addr.s_addr = inet_addr(SERIP)};struct sockaddr_in client;int client_len = sizeof(client);int server_len = sizeof(server);printf("UDP客户端启动,连接到服务器%s:%d\n",inet_ntoa(server.sin_addr),ntohs(server.sin_port));char message[20] = "UDP客户端连接";sendto(oldfd,message,strlen(message),0,(struct sockaddr *)&server,server_len);struct pollfd fds[2];fds[0].fd = oldfd;fds[0].events = POLLIN;fds[1].fd = 0;fds[1].events = POLLIN;char buff[1024];while(1){int poll_count = poll(fds,2,5000);if(poll_count == -1){perror("poll_count");return -1;}if(poll_count == 0){continue;}if(fds[0].revents == POLLIN){memset(buff,0,sizeof(buff));int len = recvfrom(oldfd,buff,sizeof(buff),0,(struct sockaddr *)&server,&server_len);if(len<0){perror("recvfrom");continue;}buff[len]='\0';printf("服务器发来消息:%s\n",buff);}if(fds[1].revents==POLLIN){memset(buff,0,sizeof(buff));if(fgets(buff,sizeof(buff),stdin)!=NULL){buff[strlen(buff)-1]='\0';sendto(oldfd,buff,strlen(buff),0,(struct sockaddr *)&server,server_len);}}}close(oldfd);return 0;
}

效果:

image-20240907162254192

使用UDP以及I/O多路复用,实现了聊天内容的转发,以及在各个终端窗口的实时显示

不足

无法识别用户并再转发时加上用户的信息

这篇关于9.7(UDP局域网多客户端聊天室)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1147041

相关文章

Redis客户端工具之RedisInsight的下载方式

《Redis客户端工具之RedisInsight的下载方式》RedisInsight是Redis官方提供的图形化客户端工具,下载步骤包括访问Redis官网、选择RedisInsight、下载链接、注册... 目录Redis客户端工具RedisInsight的下载一、点击进入Redis官网二、点击RedisI

使用Java实现获取客户端IP地址

《使用Java实现获取客户端IP地址》这篇文章主要为大家详细介绍了如何使用Java实现获取客户端IP地址,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 首先是获取 IP,直接上代码import org.springframework.web.context.request.Requ

C/C++通过IP获取局域网网卡MAC地址

《C/C++通过IP获取局域网网卡MAC地址》这篇文章主要为大家详细介绍了C++如何通过Win32API函数SendARP从IP地址获取局域网内网卡的MAC地址,感兴趣的小伙伴可以跟随小编一起学习一下... C/C++通过IP获取局域网网卡MAC地址通过win32 SendARP获取MAC地址代码#i

Python手搓邮件发送客户端

《Python手搓邮件发送客户端》这篇文章主要为大家详细介绍了如何使用Python手搓邮件发送客户端,支持发送邮件,附件,定时发送以及个性化邮件正文,感兴趣的可以了解下... 目录1. 简介2.主要功能2.1.邮件发送功能2.2.个性签名功能2.3.定时发送功能2. 4.附件管理2.5.配置加载功能2.6.

Redis连接失败:客户端IP不在白名单中的问题分析与解决方案

《Redis连接失败:客户端IP不在白名单中的问题分析与解决方案》在现代分布式系统中,Redis作为一种高性能的内存数据库,被广泛应用于缓存、消息队列、会话存储等场景,然而,在实际使用过程中,我们可能... 目录一、问题背景二、错误分析1. 错误信息解读2. 根本原因三、解决方案1. 将客户端IP添加到Re

SpringBoot实现websocket服务端及客户端的详细过程

《SpringBoot实现websocket服务端及客户端的详细过程》文章介绍了WebSocket通信过程、服务端和客户端的实现,以及可能遇到的问题及解决方案,感兴趣的朋友一起看看吧... 目录一、WebSocket通信过程二、服务端实现1.pom文件添加依赖2.启用Springboot对WebSocket

Python实现局域网远程控制电脑

《Python实现局域网远程控制电脑》这篇文章主要为大家详细介绍了如何利用Python编写一个工具,可以实现远程控制局域网电脑关机,重启,注销等功能,感兴趣的小伙伴可以参考一下... 目录1.简介2. 运行效果3. 1.0版本相关源码服务端server.py客户端client.py4. 2.0版本相关源码1

QT实现TCP客户端自动连接

《QT实现TCP客户端自动连接》这篇文章主要为大家详细介绍了QT中一个TCP客户端自动连接的测试模型,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录版本 1:没有取消按钮 测试效果测试代码版本 2:有取消按钮测试效果测试代码版本 1:没有取消按钮 测试效果缺陷:无法手动停

Nacos客户端本地缓存和故障转移方式

《Nacos客户端本地缓存和故障转移方式》Nacos客户端在从Server获得服务时,若出现故障,会通过ServiceInfoHolder和FailoverReactor进行故障转移,ServiceI... 目录1. ServiceInfoHolder本地缓存目录2. FailoverReactorinit

Java Websocket实例【服务端与客户端实现全双工通讯】

Java Websocket实例【服务端与客户端实现全双工通讯】 现很多网站为了实现即时通讯,所用的技术都是轮询(polling)。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发 出HTTP request,然后由服务器返回最新的数据给客服端的浏览器。这种传统的HTTP request 的模式带来很明显的缺点 – 浏 览器需要不断的向服务器发出请求,然而HTTP