UDP-创建群聊

news/2024/5/18 13:38:48 标签: udp, 单片机, linux

服务器

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>

#define send_port "8888"
#define send_ip "192.168.1.6"
//存储用户端信息
typedef struct user{
	struct sockaddr_in user;
	struct user* next;
	struct user* prve;
}USER;

//创建链表
USER* creat_link(void){
	USER* head=(USER*)malloc(sizeof(struct user));
	head->next=NULL;
	head->prve=NULL;
	memset(&(head->user),0,sizeof(head->user));
	return head;

}
//新用户上线
void add_link(USER* head,struct sockaddr_in usr){

	USER* uhead=(USER*)malloc(sizeof(USER));
	uhead->next=head->next;
	uhead->prve=head;
	uhead->user=usr;
	head->next=uhead;
	return ;
}

//用户下线
void delete_link(USER* head){
	USER* temp =NULL;
	temp=head->prve;
	temp->next=head->next;
	head->next->prve=temp;
	free(head);

	return ;
}



int main(int argc, const char *argv[])
{
	//创建链表
	USER* head=creat_link();


	int sockfd = socket(AF_INET,SOCK_DGRAM,0);
	if(sockfd<0){
		perror("socket");
		return -1;
	}
	int optval=1;
	int spt=setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,(void *)&optval,sizeof(optval));
	if(spt<0){
		perror("setsockopt");
		return -1;
	}

	//绑定广播地址
	struct sockaddr_in bro_addr;
	memset(&bro_addr,0,sizeof(bro_addr));
	bro_addr.sin_family=AF_INET;
	bro_addr.sin_port=htons(atoi(send_port));
	bro_addr.sin_addr.s_addr=inet_addr(send_ip);
	memset(bro_addr.sin_zero,0,sizeof(bro_addr.sin_zero));
	int bindflag=bind(sockfd,(struct sockaddr*)&bro_addr,sizeof(bro_addr));
	if(bindflag<0){
		perror("bind");
		return -1;
	}
	//创建子进程
	//int key=0;
	int pfd[2]={0};
	if(pipe(pfd)<0){
		perror("pipe");
		return -1;
	}
	printf("无名管道创建成功\n");
	pid_t pid=fork();
	if(pid>0){  	//父进程
		while(1){
			ssize_t res=0;
			USER* temp;
			res=read(pfd[0],temp,sizeof(temp));
			if(res<0){
				perror("read");
				return -1;
			}
			USER* p=(temp)->next;
			while(p!=NULL){
				printf("%d\n",__LINE__);
				char send_buf[1024];
				memset(send_buf,0,sizeof(send_buf));
				ssize_t res=0;
				res=read(pfd[0],send_buf,sizeof(send_buf));
				if(res<0){
					perror("read");
					return -1;
				}
				int sendflag=sendto(sockfd,send_buf,sizeof(send_buf),0,(struct sockaddr*)&(p->user),sizeof(p->user));
				if(sendflag<0){
					perror("sendto");
					return -1;
				}
			}
		}
	}
	/*子进程
	 * 实现客户端的查询是否有客户端上线
	 * 已上线的客户端,进行数据传输
	 * 判断是否有客户端用户要退出
	 * */
	else if(0==pid){
		while(1){
			char recv_buf[1024];//定义字符串,用于接收数据
			memset(recv_buf,0,sizeof(recv_buf));//将字符串清空
			struct sockaddr_in recv_addr;//定义一个结构体变量,用于接收IP和端口号
			memset(&recv_addr,0,sizeof(recv_addr));//清空结构体
			socklen_t len=sizeof(recv_buf);//计算字符串的大小
			int recvflag=recvfrom(sockfd,recv_buf,sizeof(recv_buf),0,(struct sockaddr *)&recv_addr,&len);//接收数据
			if(recvflag<0)//判断接收数据是否成功
			{
				printf("recvfrom error!\r\n");
				return -4;
			}
			USER* p=head;//创建一个链表节点
			int k=0;
			while(p->next!=NULL){
				p=p->next;
				in_port_t port=p->user.sin_port;
				if(port==recv_addr.sin_port){
					int i=strcmp(recv_buf,"quit");
					if(i==0){
						delete_link(p);
						p=NULL;
						k=1;
						break;
					}
					USER** phead=head;
					if(write(pfd[1],phead,sizeof(phead))<0){
						perror("地址_write");
						return -1;
					}
					if(write(pfd[1],recv_buf,sizeof(recv_buf))<0){
						perror("write");
						return -1;
					}
					printf("IP:%s PORT:%d  data:%s\n",\
							inet_ntoa(recv_addr.sin_addr),ntohs(recv_addr.sin_port),recv_buf);
					k=1;
				}
			}
			if(p->next==NULL&&0==k){
				add_link(p,recv_addr);
				printf("IP:%s   PORT:%d上线\n",\
						inet_ntoa(recv_addr.sin_addr),ntohs(recv_addr.sin_port));
			}
		}

	}
	else{
		perror("fork");
		return -1;
		
	}



	//printf("数据发送完成:%s\n",recv_buf);

	close(sockfd);

	return 0;
}

客户端

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>

#define send_port "8888"
#define send_ip "192.168.1.6"

int main(int argc, const char *argv[])
{
	int sockfd = socket(AF_INET,SOCK_DGRAM,0);
	if(sockfd<0){
		perror("socket");
		return -1;
	}
	int optval=1;
	int spt=setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,(void *)&optval,sizeof(optval));
	if(spt<0){
		perror("setsockopt");
		return -1;
	}
	struct sockaddr_in send_addr;
	memset(&send_addr,0,sizeof(send_addr));
	send_addr.sin_family=AF_INET;
	send_addr.sin_port=htons(atoi(send_port));
	send_addr.sin_addr.s_addr=inet_addr(send_ip);
	memset(send_addr.sin_zero,0,sizeof(send_addr));
	char buf[64];
	memset(buf,0,sizeof(buf));
	//fgets(buf,sizeof(buf),stdin);
	//buf[strlen(buf)-1]='\0';
	ssize_t buf_len= sizeof(buf);
	if(sendto(sockfd,buf,buf_len,0,(struct sockaddr*)&send_addr,sizeof(send_addr))<0){
		perror("sendto");
		return -1;
	}
	int pfd[2]={0};
	if(pipe(pfd)<0){
		perror("pipe");
		return-1;
	}
	pid_t pid=fork();
	if(pid>0){
		while(1){
			char buf[64];
			memset(buf,0,sizeof(buf));
			fgets(buf,sizeof(buf),stdin);
			buf[strlen(buf)-1]='\0';
			ssize_t buf_len= sizeof(buf);
			if(sendto(sockfd,buf,buf_len,0,(struct sockaddr*)&send_addr,sizeof(send_addr))<0){
				perror("sendto");
				return -1;
			}
			if(strcmp(buf,"quit")==0){
				if(write(pfd[1],buf,sizeof(buf))<0){
					perror("write");
					return -1;
				}
				printf("退出群聊\n");
				pid_t id=wait(NULL);
				break;
			}
		}

	}
	else if(pid==0){
		while(1){
			ssize_t res=0;
			char bufc[1024];
			res=read(pfd[0],bufc,sizeof(bufc));
			if(res<0){
				perror("read");
				return -1;
			}
			if(strcmp(bufc,"quit")==0){
				exit(0);
			}
			char recv_buf[1024];//定义字符串,用于接收数据
			memset(recv_buf,0,sizeof(recv_buf));//将字符串清空
			struct sockaddr_in recv_addr;//定义一个结构体变量,用于接收IP和端口号
			memset(&recv_addr,0,sizeof(recv_addr));//清空结构体
			socklen_t len=sizeof(recv_buf);//计算字符串的大小
			int recvflag=recvfrom(sockfd,recv_buf,sizeof(recv_buf),0,(struct sockaddr *)&recv_addr,&len);
			if(recvflag<0)//判断接收数据是否成功
			{
				printf("recvfrom error!\r\n");
				return -4;
			}                                                                                            
			printf("IP:%s PORT:%d  data:%s\n",\
					inet_ntoa(recv_addr.sin_addr),ntohs(recv_addr.sin_port),recv_buf);

		}

	}else{
		perror("fork");
		return -1;
	}
	printf("数据发送完成\n");
	close(sockfd);

	return 0;
}


http://www.niftyadmin.cn/n/5420539.html

相关文章

新版Android Studio火烈鸟 在新建项目工程时 无法选java的语言模板解决方法

前言 最近下载最新版androidstudio时 发现不能勾选java语言模板了 如果快速点击下一步 新建项目 默认是kotlin语言模板 这可能和google主推kt语言有关 勾选1 如图所示 如果勾选 No Activity 这个模板 是可以选java语言模板的 但是里面没有默认的Activity 勾选2 和以前的用法…

【Python使用】python高级进阶知识md总结第2篇:HTTP 请求报文,HTTP响应报文【附代码文档】

python高级进阶全知识知识笔记总结完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;操作系统&#xff0c;虚拟机软件&#xff0c;Ubuntu操作系统&#xff0c;Linux内核及发行版&#xff0c;查看目录命令&#xff0c;切换目录命令&#xff0c;绝对路径和相对…

深入了解Redis键管理:探索Redis键命令及其功能与应用场景

Redis中的键&#xff08;key&#xff09;是用于唯一标识存储在数据库中的数据的字符串。Redis提供了一系列命令来管理这些键&#xff0c;包括设置、获取、删除、设置过期时间等操作。下面详细介绍了一些与Redis键相关的常用命令和应用场景&#xff1a; 1. DEL DEL命令用于在键…

安全加速SCDN在网站运营中的重要作用

SCDN&#xff08;Secure Content Delivery Network&#xff09;是一种安全加速技术&#xff0c;对于网站运营起到非常重要的作用。它能够提升用户体验&#xff0c;保护网站安全&#xff0c;提高网站的性能和可靠性。本文将详细介绍SCDN在网站运营中的作用。 首先&#xff0c;SC…

OpenVPN的部署连接(linux客户端版),附脚本操作

上一篇文章为window的openvpn连接方式 本次为linux的openvpn连接方式&#xff0c;其实都差不多只要在服务器把证书弄好就可以了 直接上操作&#xff0c;简化操作步骤&#xff0c;服务端的操作全为脚本 实验环境 公网ip内网ip服务类型192.168.121.159客户端192.168.121.160192…

vue之性能优化

1.路由懒加载 所谓路由懒加载&#xff0c;其实就是路由通过import动态引入&#xff0c;而不是在文件最上面一个个全部引入&#xff0c;因为JS执行的时候会优先执行引入的文件&#xff0c;如果一次性引入过多&#xff0c;则会增加处理时长。 2.图片懒加载 图片在网页加载过程…

八、词嵌入语言模型(Word Embedding)

词嵌入&#xff08;Word Embedding, WE&#xff09;&#xff0c;任务是把不可计算、非结构化的词转换为可以计算、结构化的向量&#xff0c;从而便于进行数学处理。 一个更官方一点的定义是&#xff1a;词嵌入是是指把一个维数为所有词的数量的高维空间&#xff08;one-hot形式…

armv8/armv9不同特权程序之间的跳转模型

目录 1、前言2、4个特权等级/4个安全状态之间的跳转模型3、启动时镜像之间的跳转模型4、runtime程序之间的跳转模型推荐 本文转自 周贺贺&#xff0c;baron&#xff0c;代码改变世界ctw&#xff0c;Arm精选&#xff0c; armv8/armv9&#xff0c;trustzone/tee&#xff0c;secur…