网络聊天室

head.h

#ifndef __HEAD_H__
#define __HEAD_H__
 
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
 
//打印错误信息宏函数
#define ERR_MSG(msg) do{\
	fprintf(stderr,"__%d__",__LINE__);\
	perror(msg);\
}while(0)
 
//定义用户结构体
typedef struct node{
	struct sockaddr_in cin;    //存储接收到的数据包来自哪里
	socklen_t addrlen;
	char name[20];
	int stop_speaking;
	int size;
	struct node* next;
}CLI;
 
 
//创建用户结构体信息链表
CLI* create();
//判断接收到是不是新成员
int judge(CLI *H,CLI*q);
//尾插法插入新用户
int insert_cli(int sfd,CLI *H,CLI**p,char *name);
//发送信息给其他成员
int senmsg(int sfd,CLI* H,CLI*q,char *msg);
//删除指定成员
int deleat_num(int sfd,CLI *H,CLI**q);
 
//显示现有成员
void show(CLI*H);
//禁言
int stop_speak(int sfd,CLI *H,char*name);
//踢出
int get_out(int sfd,CLI*H,char *name);
//取消禁言
int stat_speak(int sfd,CLI *H,char*name);
 
#endif

main.c

#include "head.h"
 
int sfd=0;
 
void* sys_msg(void*arg)
{
	pthread_detach(pthread_self());
	CLI *H=(CLI*)arg;
	int num;
 
	while(1)
	{
		printf("************管理员************\n");
		printf("**      1,发送系统信息      **\n");
		printf("**      2,禁言              **\n");
		printf("**      3,踢出              **\n");
		printf("**      4,取消禁言          **\n");
		printf("******************************\n");
		printf("请输入选项:");
		scanf("%d",&num);
		getchar();
		switch(num)
		{
		case 1:
			{
				printf("请输入系统消息:");
				char buf[500]="";
				char arr[128]="";
				//系统信息输入
				bzero(arr,sizeof(arr));
				bzero(buf,sizeof(buf));
				strcpy(buf,"系统消息:");
 
				fgets(arr,sizeof(arr),stdin);
				arr[strlen(arr)-1]=0;
				strcat(buf,arr);
				CLI *p=H->next;
 
				//系统信息发送
				while(p!=NULL)
				{
					if(sendto(sfd,buf,strlen(buf),0,(struct sockaddr*)&(p->cin),p->addrlen)<0)
					{
						ERR_MSG("sendto");
						return NULL;
					}
					p=p->next;
				}
 
			}
			break;
		case 2:
			{
				char name[20];
				printf("请输入要禁言的名字:");
				fgets(name,sizeof(name),stdin);
				name[strlen(name)-1]=0;
				stop_speak(sfd,H,name);
			}
			break;
		case 3:
			{
				char name[20];
				printf("请输入要踢出的名字:");
				fgets(name,sizeof(name),stdin);
				name[strlen(name)-1]=0;
				get_out(sfd,H,name);
			}
			break;
		case 4:
			{
				char name[20];
				printf("请输入要取消禁言的名字:");
				fgets(name,sizeof(name),stdin);
				name[strlen(name)-1]=0;
				stat_speak(sfd,H,name);
			}
			break;
		default:printf("输入错误,请重新输入\n"); break;
		}
	}
}
 
 
 
int main(int argc, const char *argv[])
{
 
	//创建套接字
	sfd=socket(AF_INET,SOCK_DGRAM,0);
	if(sfd<0)
	{
		ERR_MSG("socket");
		return -1;
	}
 
	//填充服务器的IP地址以及端口号
	struct sockaddr_in sin;
	sin.sin_family        = AF_INET;
	sin.sin_port          = htons(8888);
	sin.sin_addr.s_addr   = inet_addr("192.168.0.132");
 
	
 
	//绑定服务器的地址信息结构体
	if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0)
	{
		ERR_MSG("bind");
		return -1;
	}
	printf("bind success\n");
 
 
	
	//创建用户结构体信息链表
	//头节点并初始化
	CLI *H=create();
 
	//创建发送系统信息线程
	pthread_t tid;
	if(pthread_create(&tid,NULL,sys_msg,(void*)H)!=0)
	{
		ERR_MSG("pthread_create");
		return -1;
	}
 
	//接收用户发送的信息
	char buf[128]="";
 
	//接收
	while(1)
	{
		bzero(buf,sizeof(buf));
 
		//申请一个新的用户信息节点
		CLI *q=(CLI*)malloc(sizeof(CLI));
		q->next=NULL;
		q->addrlen=sizeof(q->cin);
		q->size=0;
 
		//接收信息
		if(recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&(q->cin),&(q->addrlen))<0)
		{
			ERR_MSG("recvfrom");
			return -1;
		}
 
 
		//判断是不是新用户
		if(1==judge(H,q))     //是新用户,链表新增,并发信息给
		{
			insert_cli(sfd,H,&q,buf);	
		}else
		{
			if(strcmp(buf,"quit")==0)
			{
				deleat_num(sfd,H,&q);
			}else{
				senmsg(sfd,H,q,buf);
			}
		}
 
 
	}
 
	close(sfd);
	return 0;
}

test.c

#include "head.h"
 
//创建用户结构体信息链表
CLI* create()
{
	CLI *H=(CLI*)malloc(sizeof(CLI));
	if(NULL==H)
	{
		puts("创建失败\n");
		return NULL;
	}
	//初始化
	H->next=NULL;
	H->size=0;
	H->stop_speaking=0;
	strcpy(H->name,"head");
	puts("创建链表成功");
	return H;
}
 
//判断接收到是不是新成员
int judge(CLI *H,CLI*q)
{
	//判断逻辑
	if(NULL==H)
	{
		printf("链表不存在\n");
		return -1;
	}
	//判断是不是空表
	if(0==H->size)
	{
		return 1;
	}
	//循环遍历是不是新成员
	CLI*p=H->next;
	while(p!=NULL)
	{
		if(p->cin.sin_port == q->cin.sin_port)
		{
			return 0;
		}
		p=p->next;
	}
	return 1;
}
//尾插法插入新用户
int insert_cli(int sfd,CLI *H,CLI**new,char *name)
{
	CLI *p=H;
	//偏移指针
	while(p->next!=NULL)
	{
		p=p->next;
	}
	//完成尾插
	p->next=*new;
	strcpy((*new)->name,name);
	(*new)->stop_speaking=0;
 
	//表的变化
	H->size++;
	//发送登录信息给其他成员
	strcat(name,"登录成功");
 
	p=H->next;
	while(p != *new)
	{
		if(sendto(sfd,name,strlen(name),0,(struct sockaddr*)&(p->cin),p->addrlen)<0)
		{
			ERR_MSG("sendto");
			return -1;
		}
		p=p->next;
	}
 
	return 0;
}
//发送信息给其他成员
int senmsg(int sfd,CLI* H,CLI*q,char *msg)
{
 
	//封装成员名在要发送的内容前
	char arr[200]="";
	CLI*find=H->next;
	while(find!=NULL)
	{
		if((find->cin).sin_port == (q->cin).sin_port)
		{
			if(find->stop_speaking==1)
			{
				return -1;
			}
			strcpy(arr,find->name);
			strcat(arr,":");
			strcat(arr,msg);
		
		}
		find=find->next;
	}
 
	CLI*p=H->next;
	//循环发送信息
	while(p!=NULL)
	{
		if((p->cin).sin_port == (q->cin).sin_port)
		{
			p=p->next;
			continue;
		}
		if(sendto(sfd,arr,strlen(arr),0,(struct sockaddr*)&(p->cin),p->addrlen)<0)
		{
			ERR_MSG("sendto");
			return -1;
		}
		p=p->next;
	}
	return 0;
}
 
//删除指定成员
int deleat_num(int sfd, CLI *H,CLI**qe)
{
	CLI *q=*qe;
	char arr[100]="";
	//找到对应要删除的节点,封装退出字符串
	CLI*find=H;
	while(find->next!=NULL)
	{
		if(find->next->cin.sin_port == q->cin.sin_port)
		{
			strcpy(arr,find->next->name);
			strcat(arr,"退出");
			break;
		}
	}
	//删除指定成员
	CLI*temp=find->next;
	find->next=temp->next;
	free(temp);
	temp=NULL;
 
	//发送退出信息给其他成员
	CLI *p=H->next;
	while(p!=NULL)
	{
		if(sendto(sfd,arr,strlen(arr),0,(struct sockaddr*)&(p->cin),p->addrlen)<0)
		{
			ERR_MSG("sendto");
			return -1;
		}
		p=p->next;
	}
	return 0;
}
//显示现有成员
 
void show(CLI*H)
{
	CLI*p=H->next;
	while(p!=NULL)
	{
		printf("遍历:%s\n",p->name);
		p=p->next;
	}
	return;
}
//禁言
int stop_speak(int sfd,CLI *H,char*name)
{
	CLI*p=H;
	while(p!=NULL)
	{
		if(strcmp(p->name,name)==0)
		{
			p->stop_speaking=1;
			char arr[20]="stoptalking";
			sendto(sfd,arr,sizeof(arr),0,(struct sockaddr*)&(p->cin),p->addrlen);
		}
		p=p->next;
	}
	return 0;
}
//取消禁言
int stat_speak(int sfd,CLI *H,char*name)
{
	CLI*p=H;
	while(p!=NULL)
	{
		if(strcmp(p->name,name)==0)
		{
			p->stop_speaking=0;
			char arr[20]="stattalking";
			sendto(sfd,arr,sizeof(arr),0,(struct sockaddr*)&(p->cin),p->addrlen);
		}
		p=p->next;
	}
	return 0;
}
//踢出
int get_out(int sfd,CLI*H,char *name)
{
	CLI*p=H;
	while(p!=NULL)
	{
		if(strcmp(p->name,name)==0)
		{
			//通知用户端退出
			char arr[200]="quit";
			sendto(sfd,arr,sizeof(arr),0,(struct sockaddr*)&(p->cin),p->addrlen);
 
			//找到对应要删除的节点,封装退出字符串
			strcpy(arr,name);
			strcat(arr,"退出");
 
			//删除指定成员
			CLI *find=H;
			while(find->next!=NULL)
			{
				if(find->next==p) break;
			}
			CLI*temp=find->next;
			find->next=temp->next;
			free(temp);
			temp=NULL;
 
			//发送退出信息给其他成员
			CLI *p1=H->next;
			while(p1!=NULL)
			{
				if(sendto(sfd,arr,strlen(arr),0,(struct sockaddr*)&(p1->cin),p1->addrlen)<0)
				{
					ERR_MSG("sendto");
					return -1;
				}
				p1=p1->next;
			}	
			break;
		}
		p=p->next;
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值