方案二、三SELECT、UDP完成聊天室

Select 多路复用

服务器类型中

循环服务器:同一时刻只可以响应一个客户端的请求

并发服务器:同一时刻 可以响应 多个 客户端的请求

 

实现:

服务器:

1.创建socket

2.绑定 bind 记得创建server_address :( struct sockaddr_in server_addr)

3.设置监听队列 listen//(TCP这里和accept配合使用

一个while循环listen和accept(阻塞)搭配完成一次新socket创建)

//SELECT中 listen在while循环外面

/******                    上面同第一篇TCP实现原理相同                *******/

 

4.Select 用以监听fd(文件描述符 所有的~~)

(函数原型)

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

Nfds:(maxfd)代表目前已打开的 文件fd 数目 + 1

Readfds  writefds  exceptfds :

都是集合(是所有fd 的集合)

用以监听 fd 是否 可读 / 可写 / 有异常发生

作为服务器 我们只需要监听 是否可读 :客户端发起请求,服务器可以读到客户 的信息

Timeout: 是结构体 结构体内有两个值 一个秒 一个微秒

Timeout取值:

0 :不管有无 fd 可读 都直接返回

NULL: 阻塞状态 不断扫描所有的 fd 直到有 fd 发生变化 才返回

正整数:等待的最长时间t;t秒内如果没有 fd 可读 程序继续向下执行

 

 

fd_set ReadFd,TmpFd;//(是一个fd集合)用于select 参数

FD_ZERO(&ReadFd);//将两个参数初始化

FD_ZERO(&TmpFd);

FD_SET(sockfd,&ReadFd);//先将sockfd加入集合:监听是否有人发起连接

客户端不变

其余信息看代码解释

 

 

UDP:

UDP是最简单的

服务器:

  1. 创建socket
  2. 绑定 bind
  3. 接受信息 recvfrom
  4. 指定发送的对象 sendto

客户端:

  1. 创建Socket
  2. Sendto 发送信息
  3. Recvfrom 接受信息

 

 服务器:

Socket 和 bind同TCP

 

3 .  recvfrom()

(函数原型)ssize_t recvfrom(int s, void *buf, size_t len, int flags,

                         struct sockaddr *from, socklen_t *fromlen);

S :              就是自己创建的sockfd

Buf:            自己想要发送的内容

Len :           buf的大小

Flags:         默认为0

From:       就是自己本身啊 从自己发消息出去(看到这个前缀就知道 又要创建一个自己的 地址 别忘了 struct sockaddr                                                                                                                                                                                     *client_addr)

Fromlen:     是地址的长度 因为是指针所以回头 自己定义的length 记得取地址 &

 

 

客户端一样如此

 

4.sendto()

(函数原型)ssize_t  sendto(int  s,  const  void *buf, size_t len, int flags, const

                                                             struct sockaddr *to, socklen_t tolen);

S:           创建的sockfd

Buf:        接受发来的消息

Len :       buf的大小

Flags:     默认为0

To:       发送给谁(服务器啊) (看到这个前缀就知道 又要创建一个地址 别忘了 struct sockaddr *server_addr)

Tolen:     是地址的长度  这里不是指针所以不用取地址

 

 

附上源码:感觉可以的点个赞再走

TCP:

client.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sqlite3.h>

struct user
{
	char name[10];
//用户昵称
	char ID[20];
//帐号
	char password[20];
//密码
	int type;
//消息种类
	int state;
//1表示在线,0表示离线
	char toname[10];
//私聊信息发送对象
	char record[100];
//聊天记录
	int level;
//用户权限:2表示管理员,1为普通用户,0表示被禁言,-1表示被踢出        

	struct user *next;
};

char NAME[20]={0};
//用于检测有无此用户名
char NAME2[20]={0};
//用于存放登录用户的用户名
char id[20]={0};
char PASSWORD[20]={0};
int SIGN=0;
int SIGN2=10;
int SIGN3=0;
int count=0;
//记录会员的数量(只能有一个)

int Tname(void *para,int columnCount,char **columnValue,char **columnName)
{
	if(strcmp(columnValue[0],NAME) == 0)
	{
		SIGN=1;
	}

	return 0;
}

int Tid(void *para,int columnCount,char **columnValue,char **columnName)
{
	if(strcmp(columnValue[0],id) == 0)
	{
		SIGN=1;
	}

	return 0;
}

void zhuce(int sockfd)
//注册
{
	sqlite3 *pdb;
	char sql[100]={0};
	struct user User;
	int ret;

	ret=sqlite3_open("Database.db",&pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_open");
		return;
	}

	printf("****************************************\n");
	printf("           请输入您想要的昵称:\n");
	fflush(stdout);
	while(1)
	{
		scanf("%s",User.name);
		memset(NAME,0,sizeof(NAME));
		strcpy(NAME,User.name);

		sprintf(sql,"select name from user1 where name='%s';",User.name);
		ret=sqlite3_exec(pdb,sql,Tname,NULL,NULL);
		if(ret != SQLITE_OK)
		{
			perror("sqlite_exec");
			return;
		}
		if(SIGN == 0)
		//昵称未被注册
		{
			break;
		}
		else
		{
			SIGN=0;
			printf("           该已用户昵称被注册!\n");
			printf("           请重新输入用户昵称:\n");
			fflush(stdout);
		}
	}
	SIGN=0;
	//复位
	printf("\n");

	printf("           清输入您的帐号:\n");
	fflush(stdout);
	while(1)
	{
		scanf("%s",User.ID);
		memset(id,0,sizeof(id));
		strcpy(id,User.ID);

		sprintf(sql,"select ID from user1 where ID='%s';",User.ID);
		ret=sqlite3_exec(pdb,sql,Tid,NULL,NULL);
		if(ret != SQLITE_OK)
		{
			perror("sqlite_exec");
			return;
		}
		if(SIGN == 0)
		//帐号未被注册
		{
			break;
		}
		else
		{
			SIGN=0;
			printf("           该帐号已被注册!\n");
			printf("           请重新输入帐号:\n");
			fflush(stdout);
		}
	}
	SIGN=0;
	//复位

	ret=sqlite3_close(pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_close");
		return;
	}
	printf("\n");

	printf("           请输入您的密码:\n");
	fflush(stdout);
	scanf("%s",User.password);
	while(strlen(User.password) <= 5)
	{
		printf("           密码长度过短,请重新输入:\n");
		fflush(stdout);
		scanf("%s",User.password);
	}
	printf("\n");
	printf("           恭喜您用户注册成功!\n");
	printf("****************************************\n");
	sleep(2);


	User.type=1;
	//设置消息类型为注册(1)
	User.state=0;
	//表示不在线
	User.level=1;
	//表示为普通用户

	ret=send(sockfd,&User,sizeof(User),0);
	//打包发送给服务器
	if(ret == -1)
	{
		perror("send");
		return;
	}

}

int Tid2(void *para,int columnCount,char **columnValue,char **columnName)
{
	memset(NAME2,0,sizeof(NAME2));
	strcpy(NAME2,columnValue[0]);

	if(strcmp(columnValue[1],id) == 0)
	{
		SIGN=1;	
	}

	if(strcmp(columnValue[3],"1") == 0)
	{
		SIGN=2;
	}

	return 0;
}

int Tpassword(void *para,int columnCount,char **columnValue,char **columnName)
{
	if(strcmp(columnValue[0],PASSWORD) == 0)
	{
		SIGN=1;
	}

	return 0;
}

void login(int sockfd)//登录
{
	int ret;
	sqlite3 *pdb;
	char sql[100]={0};
	struct user User;

	ret=sqlite3_open("Database.db",&pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_open");
		return;
	}
	printf("********************************\n");
	printf("           清输入您的帐号:\n");
	fflush(stdout);
	while(1)
	{
		scanf("%s",User.ID);
		memset(id,0,sizeof(id));
		strcpy(id,User.ID);

		sprintf(sql,"select * from user1 where ID='%s';",User.ID);
		ret=sqlite3_exec(pdb,sql,Tid2,NULL,NULL);
		if(ret != SQLITE_OK)
		{
			perror("sqlite_exec");
			return;
		}

		if(SIGN == 1)
		{
			break;
		}
		else if(SIGN == 2)
		{
			SIGN=0;
			printf("           该帐号已在别处登录!\n");
			printf("           请重新输入:\n");
			fflush(stdout);
		}
		else
		{
			SIGN=0;
			printf("           该帐号不存在,请重新输入:\n");
			fflush(stdout);
		}		
	}
	SIGN=0;

	printf("           清输入您的密码:\n");
	fflush(stdout);
	while(1)
	{
		scanf("%s",User.password);
		memset(PASSWORD,0,sizeof(PASSWORD));
		strcpy(PASSWORD,User.password);

		sprintf(sql,"select password from user1 where ID='%s';",User.ID);
		ret=sqlite3_exec(pdb,sql,Tpassword,NULL,NULL);
		//取出user表中的帐号信息
		if(ret != SQLITE_OK)
		{
			perror("sqlite_exec");
			return;
		}

		if(SIGN == 1)
		{
			break;
		}
		else
		{
			SIGN=0;
			printf("           密码错误,请重新输入:\n");
			fflush(stdout);
		}
	}
	SIGN=0;
	printf("           登录成功!\n");
	printf("********************************\n");
	sleep(2);

	ret=sqlite3_close(pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_close");
		return;
	}

	strcpy(User.name,NAME2);

	User.type=2;
	//设置消息类型为登录(2)
	User.state=1;
	//设置用户在线

	ret=send(sockfd,&User,sizeof(User),0);
	//打包发送给服务器
	if(ret == -1)
	{
		perror("send");
		return;
	}

}

int print(void *para,int columnCount,char **columnValue,char **columnName)
{
	printf("%s:%s\n",columnName[0],columnValue[0]);

	return 0;
}

void listonline()
//查看当前在线用户
{
	sleep(1);
	system("clear");

	int ret;
	sqlite3 *pdb;
	char sql[100]={0};
	
	ret=sqlite3_open("Database.db",&pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_open");
		return;
	}
	printf("❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥\n");
	printf("          当前在线用户为:\n");

	sprintf(sql,"select name from user1 where state=1;");
	ret=sqlite3_exec(pdb,sql,print,NULL,NULL);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_exec");
		return;
	}
	printf("❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥\n");

	ret=sqlite3_close(pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_close");
		return;
	}

	sleep(2);

}

int Tlevel(void *para,int columnCount,char **columnValue,char **columnName)
//检测用户是否被禁言
{
	if(strcmp(columnValue[0],"1") == 0 || strcmp(columnValue[0],"2") == 0)
	{
		SIGN2=5;
	}

	if(strcmp(columnValue[0],"0") == 0)
	{
		SIGN2=0;
	}

	return 0;
}


int Tprivatechat(void *para,int columnCount,char **columnValue,char **columnName)
//检测用户是否存在
{
	if(strcmp(columnValue[0],NAME) == 0)
	{
		SIGN=1;
	}

	if(strcmp(columnValue[0],NAME2) == 0)
	{
		SIGN=2;
	}

	return 0;
}

//检测该用户是否在线
int Tonline(void *para,int columnCount,char **columnValue,char **columnName)
{
	if(strcmp(columnValue[0],"1") == 0)
	{
		SIGN3=1;
	}

	return 0;
}

void  chatprivate(int sockfd)
//私聊
{
	sleep(1);
	system("clear");
	printf("❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥\n");
	int ret;
	sqlite3 *pdb;
	char sql[100]={0};
	struct user User;

	ret=sqlite3_open("Database.db",&pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_open");
		return;
	}

	sprintf(sql,"select level from user1 where name='%s';",NAME2);
	ret=sqlite3_exec(pdb,sql,Tlevel,NULL,NULL);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_exec");
		return;
	}

	if(SIGN2 == 0)
	{
		printf("           您已被管理员禁言!\n");
		sleep(1);
		SIGN2=10;
		return;
	}

	printf("           请选择您想私聊的用户:\n");
	fflush(stdout);

	while(1)
	{
		SIGN=0;
		SIGN3=0;

		memset(NAME,0,sizeof(NAME));
		scanf("%s",NAME);

		sprintf(sql,"select name from user1 where name='%s';",NAME);
		ret=sqlite3_exec(pdb,sql,Tprivatechat,NULL,NULL);
		if(ret != SQLITE_OK)
		{
			perror("sqlite_exec");
			return;
		}

		sprintf(sql,"select state from user1 where name='%s';",NAME);
		ret=sqlite3_exec(pdb,sql,Tonline,NULL,NULL);
		if(ret != SQLITE_OK)
		{
			perror("sqlite_exec");
			return;
		}
		//表示存在该用户且该用户在线
		if(SIGN == 1 && SIGN3 ==1)
		{
			break;
		}
	    if(SIGN == 2)
		{
			printf("           不能和自己聊天!\n");
			printf("           请重新输入您想私聊的用户:");
			fflush(stdout);
		}
		if(SIGN3 == 0 && SIGN == 1)
		{	
			printf("           该用户不在线!\n");
			printf("           请重新输入您想私聊的用户:");
			fflush(stdout);
		}
		if(SIGN == 0)
		{
			printf("           该用户不存在!\n");
			printf("           请重新输入您想私聊的用户:");
			fflush(stdout);
		}	

	}

	ret=sqlite3_close(pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_close");
		return;
	}

	SIGN=0;
	//复位
	SIGN3=0;
	printf("❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥\n");
	printf("******聊天室******\n");
	printf("         常用表情\n");
	printf("smile ( ^_^ )  cry   T_T \n ");
	printf("sweat -_-!     angry >_< \n ");
	printf("dizzy  +_+    suprise (⊙ˍ⊙)\n");

	while(1)
	{
		User.type=3;
		//设置消息类型为私聊(3),最后哦发送给服务器;
		strcpy(User.name,NAME2);
		strcpy(User.toname,NAME);

		scanf("%s",User.record);
		if(strcmp(User.record,"end") == 0)
		{
			printf("          再见!\n");
			printf("******聊天室******\n");
			sleep(1);
			SIGN2=10;
			break;
		}

		ret=send(sockfd,&User,sizeof(User),0);
		if(ret == -1)
		{
			perror("send");
			return;
		}
		memset(&User,0,sizeof(User));
	}

}

void  chatall(int sockfd)
//群聊
{
	sleep(1);
	system("clear");

	int ret;
	struct user User;
	sqlite3 *pdb;
	char sql[100]={0};

	ret=sqlite3_open("Database.db",&pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_open");
		return;
	}

	sprintf(sql,"select level from user1 where name='%s';",NAME2);
	ret=sqlite3_exec(pdb,sql,Tlevel,NULL,NULL);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_exec");
		return;
	}

	ret=sqlite3_close(pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_close");
		return;
	}

	if(SIGN2 == 0)
	{
		printf("           您已被管理员禁言!\n");
		sleep(1);
		SIGN2=10;
		return;
	}

	printf("❥❥❥❥❥❥❥❥❥❥❥❥❥Chatting room❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥\n");
	
	while(1)
	{
		User.type=4;
		//设置消息类型为私聊(4),最后发送给发服务器;

		scanf("%s",User.record);
		if(strcmp(User.record,"end") == 0)
		{
			printf("           通话结束!\n");
			sleep(1);
			SIGN2=10;
			break;
		}

		strcpy(User.name,NAME2);

		ret=send(sockfd,&User,sizeof(User),0);
		if(ret == -1)
		{
			perror("send");
			return;
		}
		memset(&User,0,sizeof(User));
	}
}

int Tprivate(void *para,int columnCount,char **columnValue,char **columnName)
{
	if(strcmp(columnValue[0],NAME) == 0)
	{
		SIGN=1;
	}

	if(strcmp(columnValue[0],NAME2) == 0)
	{
		SIGN=2;
	}

	return 0;
}

int printprivate(void *para,int columnCount,char **columnValue,char **columnName)
//打印私聊
{
	printf("%s:%s\n",columnValue[0],columnValue[2]);

	return 0;
}

void findprivate()
{
	sleep(1);
	system("clear");

	int key=1;
	int ret;
	sqlite3 *pdb;
	char sql[100]={0};

	ret=sqlite3_open("Database.db",&pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_open");
		return;
	}

	printf("           您想查询与谁的聊天记录:");
	fflush(stdout);

	while(1)
	{
		SIGN=0;

		memset(NAME,0,sizeof(NAME));
		scanf("%s",NAME);

		sprintf(sql,"select name from user1 where name='%s';",NAME);
		ret=sqlite3_exec(pdb,sql,Tprivate,NULL,NULL);
		if(ret != SQLITE_OK)
		{
			perror("sqlite_exec");
			return;
		}
		//判断用户是否存在且不是自己
		if(SIGN == 1)
		{
			break;
		}
		else if(SIGN == 2)
		{
			printf("           您无法查询与自己的聊天记录!\n");
			printf("           请重新输入您想查询的用户:");
			fflush(stdout);
		}
		else
		{
			printf("           该用户不存在!\n");
			printf("           请重新输入您想查询的用户:");
			fflush(stdout);
		}	

	}

	SIGN=0;
	//复位

	sprintf(sql,"select * from Privatechatrecord where name='%s' AND toname='%s' OR name='%s' AND toname='%s';",NAME,NAME2,NAME2,NAME);

	ret=sqlite3_exec(pdb,sql,printprivate,NULL,NULL);		
	if(ret != SQLITE_OK)
	{
		perror("sqlite_exec");
		return;
	}

	ret=sqlite3_close(pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_close");
		return;
	}


}

int printall(void *para,int columnCount,char **columnValue,char **columnName)
//打印群聊
{
	printf("%s:%s\n",columnValue[0],columnValue[1]);

	return 0;
}

void findall()
{
	sleep(1);
	system("clear");

	int key=1;
	int ret;
	sqlite3 *pdb;
	char sql[100]={0};

	ret=sqlite3_open("Database.db",&pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_open");
		return;
	}

	sprintf(sql,"select * from Groupchatrecord;");
	ret=sqlite3_exec(pdb,sql,printall,NULL,NULL);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_exec");
		return;
	}

	ret=sqlite3_close(pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_close");
		return;
	}

}

int TVIP(void *para,int columnCount,char **columnValue,char **columnName)
//统计会员数,一开始作判断,管理数目只有一个;
{
	if(strcmp(columnValue[0],"2") == 0)
	{
		count++;
	}
	return 0;
}

void VIP(int sockfd)//vip
{
	sleep(1);
	system("clear");

	char key[2]={0};
	int ret;
	struct user User;
	sqlite3 *pdb;
	char sql[100]={0};

	ret=sqlite3_open("Database.db",&pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_open");
		return;
	}

	sprintf(sql,"select level from user1;");
	ret=sqlite3_exec(pdb,sql,TVIP,NULL,NULL);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_exec");
		return;
	}

	ret=sqlite3_close(pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_close");
		return;
	}

	if(count >= 1)
	{
		printf("           会员名额为0,请下次再来!\n");
		count=0;
		sleep(1);
		return;
	}

	printf("           确定要支付998成为会员吗?(y/n)\n");
	scanf("%s",key);
	if(key[0] == 'y')
	{
		User.type=5;
		User.level=2;
		strcpy(User.name,NAME2);

		ret=send(sockfd,&User,sizeof(User),0);
		if(ret == -1)
		{
			perror("send");
			return;
		}
		printf("           恭喜您成为会员,享受踢人禁言功能!\n");
	}
	if(key[1] == 'n')
	{
		printf("           sorry,开通失败!\n");
	}

	sleep(1);
}

int ifvip(void *para,int columnCount,char **columnValue,char **columnName)
//检验用户是否为vip
{
	if(strcmp(columnValue[0],"2") == 0)
	{
		SIGN=1;
	}

	return 0;
}

int Tcunzai(void *para,int columnCount,char **columnValue,char **columnName)
//检验用户是否存在
{
	if(strcmp(columnValue[0],NAME) == 0)
	{
		SIGN=1;
	}

	return 0;
}

void shutup(int sockfd)      
{
	sleep(1);
	system("clear");

	int ret;
	sqlite3 *pdb;
	char sql[100]={0};
	struct user User;

	ret=sqlite3_open("Database.db",&pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_open");
		return;
	}

	sprintf(sql,"select level from user1 where name='%s';",NAME2);
	ret=sqlite3_exec(pdb,sql,ifvip,NULL,NULL);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_exec");
		return;
	}

	if(SIGN == 0)
	{
		printf("           对不起,您的权限不足!\n");	
		sleep(1);
		return;
	}

	else
	{
		printf("           请选择您想禁言的用户:");
		fflush(stdout);
		while(1)
		{
			SIGN=0;
			SIGN3=0;

			scanf("%s",User.name);
			memset(NAME,0,sizeof(NAME));
			strcpy(NAME,User.name);

			sprintf(sql,"select name from user1 where name='%s';",User.name);
			ret=sqlite3_exec(pdb,sql,Tcunzai,NULL,NULL);
			if(ret != SQLITE_OK)
			{
				perror("sqlite_exec");
				return;
			}
			
			sprintf(sql,"select state from user1 where name='%s';",User.name);
			ret=sqlite3_exec(pdb,sql,Tonline,NULL,NULL);
			//判断用户是否存在且是否在线
			if(ret != SQLITE_OK)
			{
				perror("sqlite_exec");
				return;
			}

			if(SIGN == 1 && SIGN3 == 1)
			{
				break;
			}
			else if(SIGN == 1 && SIGN3 == 0)
			{
				printf("           此用户不在线!\n");
				printf("           请重新输入:");
				fflush(stdout);
			}
			else
			{
				printf("           此用户不存在!\n");
				printf("           请重新输入:");
				fflush(stdout);
			}
		}
		SIGN=0;
		User.type=6;

		ret=sqlite3_close(pdb);
		if(ret != SQLITE_OK)
		{
			perror("sqlite_close");
			return;
		}

		ret=send(sockfd,&User,sizeof(User),0);
		if(ret == -1)
		{
			perror("send");
			return;
		}
		printf("           %s用户已被禁言!\n",User.name);
		sleep(1);
	}
	
}






void jiejin(int sockfd)      
{
	sleep(1);
	system("clear");

	int ret;
	sqlite3 *pdb;
	char sql[100]={0};
	struct user User;

	ret=sqlite3_open("Database.db",&pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_open");
		return;
	}

	sprintf(sql,"select level from user1 where name='%s';",NAME2);
	ret=sqlite3_exec(pdb,sql,ifvip,NULL,NULL);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_exec");
		return;
	}

	if(SIGN == 0)
	{
		printf("           对不起,您的权限不足!\n");	
		sleep(1);
		return;
	}

	else
	{
		printf("           请选择您想解禁的用户:");
		fflush(stdout);
		while(1)
		{
			SIGN=0;
			SIGN3=0;

			scanf("%s",User.name);
			memset(NAME,0,sizeof(NAME));
			strcpy(NAME,User.name);

			sprintf(sql,"select name from user1 where name='%s';",User.name);
			ret=sqlite3_exec(pdb,sql,Tcunzai,NULL,NULL);
			if(ret != SQLITE_OK)
			{
				perror("sqlite_exec");
				return;
			}
			
			sprintf(sql,"select state from user1 where name='%s';",User.name);
			ret=sqlite3_exec(pdb,sql,Tonline,NULL,NULL);
			//判断用户是否存在且是否在线
			if(ret != SQLITE_OK)
			{
				perror("sqlite_exec");
				return;
			}

			if(SIGN == 1 && SIGN3 == 1)
			{
				break;
			}
			else if(SIGN == 1 && SIGN3 == 0)
			{
				printf("           此用户不在线!\n");
				printf("           请重新输入:");
				fflush(stdout);
			}
			else
			{
				printf("           此用户不存在!\n");
				printf("           请重新输入:");
				fflush(stdout);
			}
		}
		SIGN=0;
		User.type=9;

		ret=sqlite3_close(pdb);
		if(ret != SQLITE_OK)
		{
			perror("sqlite_close");
			return;
		}

		ret=send(sockfd,&User,sizeof(User),0);
		if(ret == -1)
		{
			perror("send");
			return;
		}
		printf("           %s用户已解除禁言!\n",User.name);
		sleep(1);
	}
	
}












void Kickout(int sockfd)
{
	sleep(1);
	system("clear");

	int ret;
	sqlite3 *pdb;
	char sql[100]={0};
	struct user User;

	ret=sqlite3_open("Database.db",&pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_open");
		return;
	}

	sprintf(sql,"select level from user1 where name='%s';",NAME2);
	ret=sqlite3_exec(pdb,sql,ifvip,NULL,NULL);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_exec");
		return;
	}

	if(SIGN == 0)
	{
		printf("           对不起,您的权限不足!\n");	
		sleep(1);
		return;
	}
	else
	{
		printf("           请选择您想踢出的用户:");
		fflush(stdout);
		while(1)
		{
			SIGN=0;
			SIGN3=0;

			scanf("%s",User.name);
			memset(NAME,0,sizeof(NAME));
			strcpy(NAME,User.name);

			sprintf(sql,"select name from user1 where name='%s';",User.name);
			ret=sqlite3_exec(pdb,sql,Tcunzai,NULL,NULL);
			if(ret != SQLITE_OK)
			{
				perror("sqlite_exec");
				return;
			}

			sprintf(sql,"select state from user1 where name='%s';",User.name);
			ret=sqlite3_exec(pdb,sql,Tonline,NULL,NULL);
			if(ret != SQLITE_OK)
			{
				perror("sqlite_exec");
				return;
			}

			if(SIGN == 1 && SIGN3 == 1)
			{
				break;
			}
			else if(SIGN == 1 && SIGN3 == 0)
			{
				printf("           此用户不在线!\n");
				printf("           请重新输入:");
				fflush(stdout);
			}
			else 
			{
				printf("           此用户不存在!\n");
				printf("           请重新输入:");
				fflush(stdout);
			}
		}
		SIGN=0;
		User.type=7;

		ret=sqlite3_close(pdb);
		if(ret != SQLITE_OK)
		{
			perror("sqlite_close");
			return;
		}

		ret=send(sockfd,&User,sizeof(User),0);
		if(ret == -1)
		{
			perror("send");
			return;
		}
		printf("           %s用户已被您踢出!\n",User.name);
		sleep(1);
	}

}

void Quit(int sockfd)
//退出
{
	sleep(1);
	system("clear");

	int ret;
	struct user User;

	User.state=0;          
	User.type=8;
	strcpy(User.name,NAME2);

	ret=send(sockfd,&User,sizeof(User),0);
	if(ret == -1)
	{
		perror("send");
		return;
	}

	printf("❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥\n");
	printf("❥❥❥❥         ʚ goodbye!~ ɞ        ❥❥❥❥ \n");
	printf("❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥\n");

	sleep(1);

}

void TERMIN()
{
	sleep(1);
	system("clear");

	printf("❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥\n");
	printf("❥❥❥❥         您选择了退出聊天室~    ❥❥❥❥\n");
	printf("❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥❥\n");

	sleep(1);
}

client-main.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<strings.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<pthread.h>


#define PORT 1234

struct user
{
	char name[10];
	char ID[20];
	char password[20];
	int type;
	int state;
	char toname[10];
	char record[100];
	int fd;
	int level;

	struct user *next;
};

pthread_t tid[2];
int out=1;                
//标志位:表示是否退出客户端


void* denglu(void *arg)
{
	int ret;
	char key1[10]={0};                 
	//登录界面功能选择按键
	char key2[10]={0};                 
	//登录后功能选择按键

	system("clear");
	printf("❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊\n");
	printf("❊❊❊❊❊     ♕   聊天室     ♕   ❊❊❊❊❊\n");
	printf("❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊\n");
	sleep(2);

	while(1)
	{
		system("clear");
		printf("❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊\n");
		printf("❊❊❊❊❊         1.注册    ❊❊❊❊❊ \n");
		printf("❊❊❊❊❊         2.登录    ❊❊❊❊❊ \n");
		printf("❊❊❊❊❊         3.退出     ❊❊❊❊❊ \n");
		printf("❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊\n");
		printf("❊❊❊❊❊         请选择您的功能         ❊❊❊❊❊\n");
		printf("❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊\n");
		scanf("%s",key1);
		switch(key1[0])
		{
			case '1':
				system("clear");
				zhuce(*(int*)arg);
				//注册界面
				break;
			case '2':
				system("clear");
				login(*(int*)arg);
				//登录界面
getin:		system("clear");
				printf("❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊\n");
				printf("❊❊❊❊❊      1.在线用户                      ❊❊❊❊❊ \n");
				printf("❊❊❊❊❊      2.私聊                               ❊❊❊❊❊ \n");
				printf("❊❊❊❊❊      3.群聊                               ❊❊❊❊❊\n");
				printf("❊❊❊❊❊      4.查询私聊记录              ❊❊❊❊❊ \n");
				printf("❊❊❊❊❊      5.查询群聊记录              ❊❊❊❊❊\n");
				printf("❊❊❊❊❊      6.开通会员                      ❊❊❊❊❊\n");
				printf("❊❊❊❊❊      7.禁言                               ❊❊❊❊❊\n");
				printf("❊❊❊❊❊      8.踢人                              ❊❊❊❊❊ \n");
				printf("❊❊❊❊❊      9.退出                              ❊❊❊❊❊ \n");
				printf("❊❊❊❊❊      0.解禁                             ❊❊❊❊❊ \n");
				printf("❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊\n");
				printf("❊          请选择您的功能                           ❊\n");
				printf("❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊\n");
				scanf("%s",key2);
				switch(key2[0])
				{
					case '1':
							listonline();
							//查看在线用户
							sleep(2);
							goto getin;
					case '2':
							chatprivate(*(int*)arg);
							//私聊
							sleep(2);
							goto getin;
					case '3':
							chatall(*(int*)arg);
							//群发
							sleep(2);
							goto getin;
					case '4':
							findprivate();
							//查询私聊记录
							sleep(2);
							goto getin;
					case '5':
							findall();
							//查询群聊记录
							sleep(2);
							goto getin;
					case '6':
							VIP(*(int*)arg);
							//开通会员
							sleep(2);
							goto getin;
					case '7':
							shutup(*(int*)arg);
							//禁言
							sleep(2);
							goto getin;
					case '8':
							Kickout(*(int*)arg);    
							//踢人
							sleep(2);
							goto getin;
					case '9':
							Quit(*(int*)arg);       
							//退出界面
							sleep(2);
							break;
					case '0':
							jiejin(*(int*)arg);
							//解除禁言
							sleep(2);
							goto getin;
					default:
							printf("❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊\n");
							printf("❊❊❊❊❊     错误按钮(登录后)!  ❊❊❊❊❊\n");
							printf("❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊\n");
							sleep(2);
							goto getin;	
				}
						break;
			case '3':
						goto breakout;
			default:
						printf("❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊\n");
						printf("❊❊❊❊❊     错误按钮(登录前)! ❊❊❊❊❊\n");
						printf("❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊\n");
				printf("错误按钮(登录前)!\n");
				break;
		}
	}

	breakout:TERMIN();
	//退出客户端
	out=0;
	//复位
	pthread_cancel(tid[0]);
	//退出客户端后,将接受信息的进程杀死,不然一直阻塞在那里
	
}

void* Receive(void *arg)
{
	int ret;
	struct user User;

	while(1)
	{
		memset(&User,0,sizeof(User));
		ret=recv(*(int*)arg,&User,sizeof(User),0);
		if(ret == -1)
		{
			perror("recv");
			exit(1);
		}

		if(User.type == 3)
		//私聊
		{
			printf("%s:%s\n",User.name,User.record);
		}

		if(User.type == 4)
		//群发
		{
			printf("%s:%s\n",User.name,User.record);
		}

		if(User.type == 7)
		//踢人
		{
			break;
		}

	}
}

int main()
{
	int sockfd;
	int ret;
	char key1[10]={0};
	//登录选择
	char key2[10]={0};
	//登录后选择
	struct sockaddr_in server_addr;

	sockfd=socket(PF_INET,SOCK_STREAM,0);
	if(sockfd == -1)
	{
		perror("socket");
		exit(1);
	}

	bzero(&server_addr,sizeof(server_addr));
	server_addr.sin_family=PF_INET;
	server_addr.sin_port=htons(PORT);
	server_addr.sin_addr.s_addr=inet_addr("127.0.0.1");

	ret=connect(sockfd,(struct sockaddr *)&server_addr,sizeof(server_addr));
	//连接服务器
	if(ret == -1)
	{
		perror("connect");
		exit(1);
	}

	while(1)
	{
		ret=pthread_create(&tid[0],NULL,Receive,(void*)&sockfd);
		if(ret != 0)
		{
			perror("pthread_create");
			exit(1);
		}

		ret=pthread_create(&tid[1],NULL,denglu,(void*)&sockfd);
		if(ret != 0)
		{
			perror("pthread_create");
			exit(1);
		}

		pthread_join(tid[0],NULL);
		if(out == 0)
		{
			break;
		}
		pthread_cancel(tid[1]);
		//先退出登录后的界面,回到注册登录退出界面,完成被踢就退出的功能

		printf("❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊\n");
		printf("❊❊❊❊❊   您被管理员踢出了聊天室!  ❊❊❊❊❊\n");
		printf("❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊❊\n");

		sleep(3);
	}

	return 0;
}

server.c

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

struct user
{
	char name[10];
	char ID[20];
	char password[20];
	int type;
	int state;
	char toname[10];
	char record[100];
	int fd;
	int level;

	struct user *next;
};

int tofd=0;
//私聊的通信管道号
char NAME[20]={0};
//暂时存储用户昵称
int onlineflag=0;               

void zhuce(struct user User,int fd)
//消息类型1:注册
{
	int ret;
	sqlite3 *pdb;
	char sql[100]={0};

	ret=sqlite3_open("Database.db",&pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite3_open");
		return;													
	}	

	sprintf(sql, "create table if not exists user1 (name text,ID text,password text,state integer,level integer);");
	//继续使用user1表				
	ret=sqlite3_exec(pdb,sql,NULL,NULL,NULL);							
	if(ret != SQLITE_OK)
	{
		perror("sqlite_create");								
		return;
	}

	sprintf(sql,"insert into user1 (name,ID,password,state,level) values('%s','%s','%s',%d,%d);",User.name,User.ID,User.password,User.state,User.level);
	//插入用户信息
	ret=sqlite3_exec(pdb,sql,NULL,NULL,NULL);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_insert");
		return;
	}

	ret=sqlite3_close(pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_close");
		return;
	}
}

void login(struct user User,int fd)
//消息类型12:登录
{
	int ret;
	sqlite3 *pdb;
	char sql[100]={0};

	ret=sqlite3_open("Database.db",&pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite3_open");
		return;
	}

	sprintf(sql,"create table if not exists user2 (name text,fd integer);");
	//继续使用user2表			
	ret=sqlite3_exec(pdb,sql,NULL,NULL,NULL);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_create");
		return;
	}

	sprintf(sql,"insert into user2(name,fd) values('%s',%d);",User.name,fd);
	//将客户端的通信管道号插入表中
	ret=sqlite3_exec(pdb,sql,NULL,NULL,NULL);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_update");
		return;
	}

	sprintf(sql,"update user1 set state=1 where ID='%s';",User.ID);
	//设置在线
	ret=sqlite3_exec(pdb,sql,NULL,NULL,NULL);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_update");
		return;
	}

	ret=sqlite3_close(pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_close");
		return;
	}				
}

void Turn(char a[])
{
	if(strcmp(a,"smile") == 0)
	{
		strcpy(a,"( ^_^ )");
	}
	if(strcmp(a,"cry") == 0)
	{
		strcpy(a,"T_T");
	}
	if(strcmp(a,"sweat") == 0)
	{
		strcpy(a,"-_-!");
	}
	if(strcmp(a,"angry") == 0)
	{
		strcpy(a,">_<");
	}
	if(strcmp(a,"dizzy") == 0)
	{
		strcpy(a,"+_+");
	}
	if(strcmp(a,"suprise") == 0)
	{
		strcpy(a,"(⊙ˍ⊙)");
	}
}

int assign(void *para,int columnCount,char **columnValue,char **cloumnName)
//通过用户昵称找到通信管道号
{
	tofd=atoi(columnValue[0]);

	return 0;
}

void chatprivate(struct user User,int fd)
//消息类型13:私聊
{
	int ret;
	sqlite3 *pdb;
	char sql[100]={0};

	ret=sqlite3_open("Database.db",&pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite3_open");
		return;
	}

	sprintf(sql,"select fd from user2 where name='%s';", User.toname);
	ret=sqlite3_exec(pdb,sql,assign,NULL,NULL);
	if(ret != SQLITE_OK)
	{
		perror("sqlite3_exec");
		return;
	}

	Turn(User.record);
	//将文字转换为表情符号

	ret=send(tofd,&User,sizeof(User),0);	
	if(ret == -1)
	{
		perror("send");
		return;
	}

	sprintf(sql, "create table if not exists Privatechatrecord (name text,toname text,record text);");		
	//创建Privatechat表
	ret=sqlite3_exec(pdb,sql,NULL,NULL,NULL);							
	if(ret != SQLITE_OK)
	{
		perror("sqlite_create");								
		return;
	}

	sprintf(sql,"insert into Privatechatrecord (name,toname,record) values('%s','%s','%s');",User.name,User.toname,User.record);
	//存储私聊
	ret=sqlite3_exec(pdb,sql,NULL,NULL,NULL);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_insert");
		return;
	}
	
	ret=sqlite3_close(pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_close");
		return;
	}

	tofd=0;
}

int Tstate(void *para,int columnCount,char **columnValue,char **columnName)
//检测是否在线
{
	if(strcmp(columnValue[0],"0") != 0)
	{
		onlineflag=1;
	}

	return 0;
}

void chatall(struct user User,int source_fd,int fd[],int k)
//消息类型14:群聊
{
	int i;
	int ret;
	sqlite3 *pdb;
	char sql[100]={0};

	Turn(User.record);

	ret=sqlite3_open("Database.db",&pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite3_open");
		return;
	}

	sprintf(sql, "create table if not exists Groupchatrecord (name text,record text);");
	//创建Groupchat表				
	ret=sqlite3_exec(pdb,sql,NULL,NULL,NULL);							
	if(ret != SQLITE_OK)
	{
		perror("sqlite_create");								
		return;
	}

	sprintf(sql,"insert into Groupchatrecord (name,record) values('%s','%s');",User.name,User.record);
	//存储群聊
	ret=sqlite3_exec(pdb,sql,NULL,NULL,NULL);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_insert");
		return;
	}

	for(i=0;i<k;i++)
	{
		if(fd[i] == source_fd)
		//给除了自己以外的用户发送消息
		{
			continue;
		}
		sprintf(sql,"select fd from user2 where fd='%d';",fd[i]);
		ret=sqlite3_exec(pdb,sql,Tstate,NULL,NULL);
		if(ret != SQLITE_OK)
		{
			perror("sqlite_exec");
			return;
		}

		if(onlineflag == 1)
		{
			ret=send(fd[i],&User,sizeof(User),0);
			if(ret == -1)
			{
				perror("send");
				return;
			}
			onlineflag=0;
		}
	}

	ret=sqlite3_close(pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_close");
		return;
	}	

}

void VIP(struct user User)
//消息类型15:开通会员
{
	int ret;
	sqlite3 *pdb;
	char sql[100]={0};

	ret=sqlite3_open("Database.db",&pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite3_open");
		return;
	}

	sprintf(sql,"update user1 set level=2 where name='%s';",User.name);
	//更新用户权限为管理员
	ret=sqlite3_exec(pdb,sql,NULL,NULL,NULL);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_update");
		return;
	}

	ret=sqlite3_close(pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_close");
		return;
	}				

}

void shutup(struct user User)
//消息类型16:禁言
{
	int ret;
	sqlite3 *pdb;
	char sql[100]={0};

	ret=sqlite3_open("Database.db",&pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite3_open");
		return;
	}

	sprintf(sql,"update user1 set level=0 where name='%s';",User.name);
	//更新用户权限为被禁言
	ret=sqlite3_exec(pdb,sql,NULL,NULL,NULL);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_update");
		return;
	}

	ret=sqlite3_close(pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_close");
		return;
	}				

}

void kickout(struct user User)
//消息类型17:踢人
{	
	int ret;
	sqlite3 *pdb;
	char sql[100]={0};

	ret=sqlite3_open("Database.db",&pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite3_open");
		return;
	}

	sprintf(sql,"update user1 set state=0 where name='%s';",User.name);
	//更新用户不在线
	ret=sqlite3_exec(pdb,sql,NULL,NULL,NULL);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_update");
		return;
	}

	sprintf(sql,"select fd from user2 where name='%s';", User.name);
	//找到对应通信管道号
	ret=sqlite3_exec(pdb,sql,assign,NULL,NULL);
	if(ret != SQLITE_OK)
	{
		perror("sqlite3_exec");
		return;
	}

	sprintf(sql,"delete from user2 where name='%s';",User.name);
	//将被踢用户从表中删除
	ret=sqlite3_exec(pdb,sql,NULL,NULL,NULL);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_delete");
		return;
	}

	ret=sqlite3_close(pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_close");
		return;
	}	

	ret=send(tofd,&User,sizeof(User),0);
	if(ret == -1)
	{
		perror("send");
		return;
	}

	tofd=0;
}

void quit(struct user User)
//消息类型18:退出
{
	int ret;
	sqlite3 *pdb;
	char sql[100]={0};

	ret=sqlite3_open("Database.db",&pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite3_open");
		return;
	}

	sprintf(sql,"update user1 set state=0 where name='%s';",User.name);
	//更新用户不在线
	ret=sqlite3_exec(pdb,sql,NULL,NULL,NULL);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_update");
		return;
	}

	sprintf(sql,"delete from user2 where name='%s';",User.name);
	//将用户从表中删除
	ret=sqlite3_exec(pdb,sql,NULL,NULL,NULL);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_delete");
		return;
	}

	ret=sqlite3_close(pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_close");
		return;
	}				
	
}
void jiejin(struct user User)
//消息类型16:禁言
{
	int ret;
	sqlite3 *pdb;
	char sql[100]={0};

	ret=sqlite3_open("Database.db",&pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite3_open");
		return;
	}

	sprintf(sql,"update user1 set level=1 where name='%s';",User.name);
	//更新用户权限为解除禁言
	ret=sqlite3_exec(pdb,sql,NULL,NULL,NULL);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_update");
		return;
	}

	ret=sqlite3_close(pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_close");
		return;
	}				

}

server_main.c

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


#define PORT 1234

struct user
{
	char name[10];
	char ID[20];
	char password[20];
	int type;
	int state;
	char toname[10];
	char record[100];
	int fd;
	int level;

	struct user *next;
};

int main()
{
	int sockfd;
	int ret;
	int fd[100];                 
	int MaxFd;
	int i=0,j;
	fd_set ReadFd,TmpFd;
	struct sockaddr_in server_addr;
	struct sockaddr_in client_addr;
	struct user User;

	sqlite3 *pdb;
	char sql[100]={0};

	ret=sqlite3_open("Database.db",&pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite3_open");
		exit(1);
	}

	sprintf(sql,"create table if not exists user1 (name text,ID text,password text,state integer,level integer);");  
	//创建user1表				
	ret=sqlite3_exec(pdb,sql,NULL,NULL,NULL);							
	if(ret != SQLITE_OK)
	{
		perror("sqlite_create1");								
		exit(1);
	}

	sprintf(sql,"create table if not exists user2 (name text,fd integer);");
	//创建user2表				
	ret=sqlite3_exec(pdb,sql,NULL,NULL,NULL);							
	if(ret != SQLITE_OK)
	{
		perror("sqlite_create1");								
		exit(1);
	}

	sprintf(sql,"create table if not exists Privatechatrecord (name text,toname text,record text);");
	//创建Private chat record表				
	ret=sqlite3_exec(pdb,sql,NULL,NULL,NULL);							
	if(ret != SQLITE_OK)
	{
		perror("sqlite_create2");								
		exit(1);
	}

	sprintf(sql, "create table if not exists Groupchatrecord (name text,record text);");
	//创建Group chat record表				
	ret=sqlite3_exec(pdb,sql,NULL,NULL,NULL);							
	if(ret != SQLITE_OK)
	{
		perror("sqlite_create3");								
		exit(1);
	}
	
	ret=sqlite3_close(pdb);
	if(ret != SQLITE_OK)
	{
		perror("sqlite_close");
		exit(1);
	}	





	sockfd=socket(PF_INET,SOCK_STREAM,0);
	//创建平台
	if(sockfd == -1)
	{
		perror("socket");
		exit(1);
	}

	int opt=1;
	setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
	//允许多开,避免地址覆盖

	bzero(&server_addr,sizeof(server_addr));
	server_addr.sin_family=PF_INET;
	server_addr.sin_port=htons(PORT);
	server_addr.sin_addr.s_addr=htonl(INADDR_ANY);

	ret=bind(sockfd,(struct sockaddr*)&server_addr,sizeof(server_addr));
	//把自己绑定好
	if(ret == -1)
	{
		perror("bind");
		exit(1);
	}

	ret=listen(sockfd,10);
	//监听信息
	if(ret == -1)
	{
		perror("listen");
		exit(1);
	}

	FD_ZERO(&ReadFd);
	FD_ZERO(&TmpFd);
	FD_SET(sockfd,&ReadFd);
	MaxFd=sockfd;

	while(1)
	{
		TmpFd=ReadFd;
		ret=select(MaxFd+1,&TmpFd,NULL,NULL,NULL);
		//用select阻塞
		if(ret == -1)
		{
			perror("select");
			exit(1);
		}

		if(FD_ISSET(sockfd,&TmpFd))//看看是不是 有客户(fd)向服务sockfd发起连接
		{
			int length=sizeof(client_addr);
			fd[i]=accept(sockfd,(struct sockaddr*)&client_addr,&length);//如果有 则sockfd接受 保存客户信息
			if(fd[i] == -1)
			{
				perror("accept");
				exit(1);
			}
			FD_SET(fd[i],&ReadFd);//将客户加入监听集合
			MaxFd=fd[i];//更新maxfd 
			i++;//每有一个客户发起连接 人数加一
		}
		else//fd 在发消息
		{
			for(j=0;j<i;j++)
			{
				if(FD_ISSET(fd[j],&TmpFd))//查看是哪个客户在发消息 引起了fd 的变化
				{
					memset(&User,0,sizeof(User));
					ret=recv(fd[j],&User,sizeof(User),0);
					if(ret == -1)
					{
						perror("recv");
						exit(1);
					}

					if(User.type == 1)
					//消息类型1:注册
					{
						zhuce(User,fd[j]);				
					}

					if(User.type == 2)
					//消息类型12:登录
					{
						login(User,fd[j]);		
					}

					if(User.type == 3)
					//消息类型13:私聊
					{
						chatprivate(User,fd[j]);
					}
					
					if(User.type == 4)
					//消息类型14:群聊
					{
						chatall(User,fd[j],fd,i);
					}

					if(User.type == 5)
					//消息类型15:开通会员
					{
						VIP(User);  
					}

					if(User.type == 6)
					//消息类型16:禁言
					{
						shutup(User);
					}

					if(User.type == 7)
					//消息类型17:踢人
					{
						kickout(User);
					}

					if(User.type == 8)
					//消息类型18:退出
					{
						quit(User);
					}
					if(User.type == 9)
					//消息类型18:退出
					{
						jiejin(User);
					}

				}
			}
		}
	}

	return 0;
}

UDP参考网上小姐姐的代码 我做了封装

#ifndef _CHAT_H_
#define _CHAT_H_

#include <stdio.h>  
#include <sqlite3.h>  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <string.h>  
#include <strings.h>  
#include <stdlib.h>  
#include <netinet/in.h>  //包含socketaddr_in
#include <arpa/inet.h>  
#include <unistd.h>  
#include <signal.h>  
#include <pthread.h>  
#include <semaphore.h>  
#include <termios.h>  
#include <time.h>  
#include <sys/stat.h>  
#include <fcntl.h>  

#define PORT          9999

#define reg             11   //注册,cmd
#define reg_success     12   //注册成功
#define existing        13   //账号已存在
#define log_in          14   //登录,cmd
#define log_success     15   //登录成功
#define logged          16   //账号已登录
#define log_error       17   //账号或密码错误

#define private_chat    18   //私聊
#define group_chat      19   //群聊
#define Gchat_failure   20   //群聊失败
#define online          21   //在线人数
#define Vip             22   //会员
#define shutup          23   //禁言
#define relieve         24   //解除禁言
#define kick            25   //踢人
#define face            26   //群发表情
#define send_useful     27   //发送常用语
#define Exit            28   //退出
#define quit            31   //下线

#define Send_success    29   //发送成功
#define Pchat_failure   30   //私聊失败 
#define Send_failure    32   //发送失败
#define face_failure    33   //发送表情失败
#define vip_success     34   //开通会员成功
#define shutup_success  35   //禁言成功
#define kick_success    36   //踢人成功
#define shutup_failure  37   //禁言失败
#define kick_failure    38   //踢人失败

#endif 

client_function.h

#ifndef _CLIENT_H_
#define _CLIENT_H_

struct info
{
	char username[20];          //用户名     
	char password[20];          //密码   
	int cmd;                    //提取操作类型  
	int result;                 //返回标记
	int port;                   //端口号
	char message[50];			//保存信息
	char toname[20];			//发送给谁
	char fromname[20];			//从谁那里接收
	char online_name[20][20];	//在线人员名单
	int num;
	int p_f;
	char emoj[20];				//表情
	int p_u;
	char useful[20];
	int vip;
	char question[50];
	char answer[50];
	char file_name[50];
	char file_content[2048];
};

//时间函数 自己百度查找
void time_show();

void welcome(void);

void bye(void);

void show();

//防止空格影响
void SCAN_N();

//登录之后的聊天界面
int chatshow();

//注册 将注册信息发送给服务器 进行注册 这里是确认注册信息的过程
int Register();

//登录  同上 确认登录信息
int Login();

//处理登陆后的函数
int deal_login();

//接收服务器发送的结果的接口函数
void *Recv_Server(void *arg);

#endif

client_main.c

\

#include "clientfunction.h"
#include "chat.h"


struct info RecvBuf;				//接收方	的信息保存
struct info SendBuf;				//发送方	的信息保存

struct sockaddr_in server_addr;		//记录服务器地址 便于信息传输

char name[20] = { 0 };
int ret;
int sockfd;
int flag;
int out = 0;

//时间函数 自己百度查找
void time_show()
{
	time_t rawtime;
	struct tm *timeinfo;
	time(&rawtime);
	timeinfo = localtime(&rawtime);
	printf("时间: %d 年 %d 月 %d 日 %d 时 %d 分 %d 秒\n\n", timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
		timeinfo->tm_mday, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);

}

void welcome(void)
{
	system("clear");
	printf("\t\t\t*********************************************\n");
	printf("\t\t\t*                                           *\n");
	printf("\t\t\t*                                           *\n");
	printf("\t\t\t*                                           *\n");
	printf("\t\t\t*        Welcome To UDP Chatting Room !     *\n");
	printf("\t\t\t*                                           *\n");
	printf("\t\t\t*                                           *\n");
	printf("\t\t\t*                                           *\n");
	printf("\t\t\t*                                           *\n");
	printf("\t\t\t*********************************************\n");

	sleep(2);
}

void bye(void)
{
	system("clear");
	printf("\t\t\t*********************************************\n");
	printf("\t\t\t\t*                                           *\n");
	printf("\t\t\t*                                           *\n");
	printf("\t\t\t*                                           *\n");
	printf("\t\t\t*        Hope To See You Again !            *\n");
	printf("\t\t\t*                                           *\n");
	printf("\t\t\t*                                           *\n");
	printf("\t\t\t*                                           *\n");
	printf("\t\t\t*                                           *\n");
	printf("\t\t\t*********************************************\n");

	sleep(2);

}

void show()
{
	system("clear");
	printf("\t\t\t**********************************************\n");
	printf("\t\t\t*                                            *\n");
	printf("\t\t\t*     UDP聊天室                              *\n");
	printf("\t\t\t*                                            *\n");
	printf("\t\t\t*     1  注册                                *\n");
	printf("\t\t\t*     2  登录                                *\n");
	printf("\t\t\t*     3  退出                                *\n");
	printf("\t\t\t*                                            *\n");
	printf("\t\t\t*     请输入选择:                           *\n");
	printf("\t\t\t**********************************************\n");
}

//防止空格影响
void SCAN_N()
{
	char ch;
	while ((getchar()) != '\n' && ch != EOF);//消除非法输入
}

//登录之后的聊天界面
int chatshow()
{
	system("clear");
	printf("\t\t\t");
	time_show();

	printf("\t\t\t**********************************************\n");
	printf("\t\t\t*     UDP聊天室!祝您聊天愉快!               *\n");
	printf("\t\t\t*     用户名:%s                             *\n", name);
	if (SendBuf.vip == 1)
	{
		printf("\t\t\t*   尊贵的会员                           *\n");
	}
	else
	{
		printf("\t\t\t*   普通用户                             *\n");
	}
	printf("\t\t\t*                                            *\n");
	printf("\t\t\t*                a 私聊                      *\n");
	printf("\t\t\t*                b 群聊                      *\n");
	printf("\t\t\t*                c 查看在线人数              *\n");
	printf("\t\t\t*                d 发送表情                  *\n");
	printf("\t\t\t*                e 常用语                    *\n");
	printf("\t\t\t*                f 开通会员                  *\n");
	printf("\t\t\t*                g 禁言(需开通会员)          *\n");
	printf("\t\t\t*                h 踢人(需开通会员)          *\n");
	printf("\t\t\t*                i 查看聊天记录              *\n");
	printf("\t\t\t*                j 解禁                      *\n");
	printf("\t\t\t*                k 退出                      *\n");
	printf("\t\t\t*                请输入您的选择:            *\n");
	printf("\t\t\t**********************************************\n");
}

//注册 将注册信息发送给服务器 进行注册 这里是确认注册信息的过程
int Register()
{
	flag = 0;
	system("clear");
	SendBuf.cmd = reg;
	char pass1[20] = { 0 };
	char pass2[20] = { 0 };

	printf("\t\t\t注册中......\n");
	printf("\n\n");
	printf("\t\t\t请输入你的用户名:\n");
	printf("\t\t\t");
	scanf("\t\t\t%s", SendBuf.username);
	SCAN_N();
	printf("\t\t\t请输入你的密码:\n");
	printf("\t\t\t");
	scanf("\t\t\t%s", pass1);
	SCAN_N();
	printf("\t\t\t请确认你的密码:\n");
	printf("\t\t\t");
	scanf("\t\t\t%s", pass2);
	SCAN_N();

	if (strcmp(pass1, pass2) != 0)
	{
		printf("\t\t\t密码输入不一致!请重新输入密码!\n");
		printf("请在此重新输入你的密码:\n");
		scanf("%s", pass2);
	}
	else
	{
		strcpy(SendBuf.password, pass1);
	}
}

//登录  同上 确认登录信息
int Login()
{
	system("clear");
	SendBuf.cmd = log_in;
	printf("\t\t\t登录中......\n");
	printf("\n\n");
	printf("\t\t\t请输入你的账号:\n");
	printf("\t\t\t");
	scanf("\t\t\t%s", SendBuf.username);
	SCAN_N();
	printf("\t\t\t请输入你的密码:\n");
	printf("\t\t\t");
	scanf("\t\t\t%s", SendBuf.password);

}

//处理登陆后的函数
int deal_login()
{
	if (out == 1)
	{
		out--;
		return Exit;
	}

	char choice2[10] = { 0 };
	char file[2048] = { 0 };
	char filename[50] = { 0 };
	int fd;

	while (1)
	{
		chatshow();

		scanf("%s", choice2);			//读入用户选择的功能字母

		switch (choice2[0])
		{
		case 'a':					//私聊  
		{
			system("clear");		//清屏

			if (flag == 23)			//判断是否被禁言
			{
				printf("\n\t\t\t您已经被禁言了!\n");
				sleep(2);
				break;
			}

			printf("\t\t\t请输入对方的名字:\n");
			printf("\t\t\t");
			scanf("%s", SendBuf.toname);
			SCAN_N();

			printf("\t\t\t请输入您想要说的话:\n");
			printf("\t\t\t");
			scanf("%s", SendBuf.message);
			SCAN_N();

			SendBuf.cmd = private_chat;		//操作符 为私聊

			strcpy(SendBuf.username, name);

			if (strcmp(SendBuf.toname, name) == 0)
			{
				sleep(1);
				system("clear");
				printf("\t\t\t不可以给自己发信息!\n");
				printf("\t\t\t请重新输入用户名!\n");
				break;
			}

			ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
			/*		发送给服务器 我要私聊某某		*/
			if (ret < 0)
			{
				perror("sendto_pchat");
				exit(1);
			}

			sprintf(filename, "%s chat with %s.txt", name, SendBuf.toname);
			fd = open(filename, O_CREAT | O_RDWR | O_APPEND, S_IRUSR | S_IWUSR);
			if (fd == -1)
			{
				perror("open");
				exit(1);
			}

			sprintf(file, "%s 给 %s 发送了一条消息:%s", name, SendBuf.toname, SendBuf.message);
			ret = write(fd, file, strlen(file));
			if (ret == -1)
			{
				perror("write");
				exit(1);
			}
			printf("\t\t\t\t发送中...\n");
			sleep(2);

			break;
		}

		case 'b'://群聊
		{
			system("clear");

			if (flag == 23)		//同上
			{
				printf("\n\t\t\t您已经被禁言了!\n");
				sleep(2);
				break;
			}

			printf("\t\t\t请发送消息:\n");

			scanf("%s", SendBuf.message);

			SendBuf.cmd = group_chat;

			strcpy(SendBuf.username, name);
			ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
			if (ret < 0)
			{
				perror("sendto_groupchat");
				exit(1);
			}
			printf("\t\t\t发送中......\n");
			sleep(2);
			break;
		}

		case 'c': //查看在线人数
		{
			system("clear");
			SendBuf.cmd = online;			//操作符 查看在线
			ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
			if (ret < 0)
			{
				perror("sendto_onlinenum");
				exit(1);
			}
			sleep(3);			//注意如果人数很多 睡眠时间建议稍微长点 不然查看的效果很差
			break;
		}

		case 'd':  //群发表情
		{
			system("clear");

			if (flag == 23)
			{
				printf("\n\t\t\t您已经被禁言了!\n");
				sleep(2);
				break;
			}

			char choice3[10] = { 0 };

			SendBuf.cmd = face;

			printf("\t\t\t**************************\n");
			printf("\t\t\t1 感动   ≧◇≦  \n");
			printf("\t\t\t2 无奈   ╮( ̄▽  ̄)╭\n");
			printf("\t\t\t3 哭泣   T_T\n");
			printf("\t\t\t4 惊讶   ⊙?⊙\n");
			printf("\t\t\t5 喵 (= ̄ω ̄=)\n");
			printf("\t\t\t6 害羞  (# ̄▽ ̄#)\n");
			printf("\t\t\t请输入你的选择\n");
			scanf("%s", choice3);

			SendBuf.p_f = choice3[0];

			strcpy(SendBuf.username, name);
			ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
			if (ret < 0)
			{
				perror("sendto_face");
				exit(1);
			}
			printf("\t\t\t发送中......\n");
			sleep(2);
			break;

		}

		case 'e':   //发送常用语
		{
			system("clear");

			if (flag == 23)
			{
				printf("\n\t\t\t您已经被禁言了!\n");
				sleep(2);
				break;
			}

			char choice4[10] = { 0 };

			printf("\t\t\t请输入对方的名字:\n");
			printf("\t\t\t");
			scanf("%s", SendBuf.toname);

			strcpy(SendBuf.username, name);

			SendBuf.cmd = send_useful;

			printf("\t\t\t**************************\n");
			printf("\t\t\t1 I see. 我明白了.\n");
			printf("\t\t\t2 My god! 天哪!\n");
			printf("\t\t\t3 No way! 不行!\n");
			printf("\t\t\t4 Cheer up! 振作起来!\n");
			printf("\t\t\t5 Good job! 做得好!\n");
			printf("\t\t\t6 Bless you! 祝福你!\n");
			printf("\t\t\t7 Thank you! 谢谢!\n");
			printf("\n\t\t请输入你想发送的常用语:\n");
			scanf("%s", choice4);
			SCAN_N();
			SendBuf.p_u = choice4[0];

			if (strcmp(name, SendBuf.toname) == 0)
			{
				sleep(1);
				system("clear");
				printf("\t\t\t不可以给自己发送常用语");
				printf("\t\t\t请重新输入用户名!\n");
				return -1;
			}

			ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
			if (ret < 0)
			{
				perror("sendto_useful");
				exit(1);
			}
			printf("\n\t\t正在发送...\n");
			sleep(2);
			break;
		}

		case 'f':   //开通会员
		{
			system("clear");
			if (SendBuf.vip == 0)
			{
				char a[2];
				system("clear");
				printf("\n\n\n\t\t\t您确定要支付十万块成为会员吗?\n");
				printf("\n\t\t\t您确认支付吗?(y/n)");
				scanf("%s", a);

				if (a[0] == 'y')
				{
					strcpy(SendBuf.username, name);
					SendBuf.vip = 1;
					SendBuf.cmd = Vip;

					ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
					if (ret < 0)
					{
						perror("sendto_vip");
						exit(1);
					}
					printf("\n\n\t\t请稍等...\n");
					sleep(2);
				}
				else
				{
					break;
				}
			}
			else if (SendBuf.vip == 1)
			{
				printf("您已经是会员了,无需再次开通!\n");
			}
			break;
		}

		case 'g':   //禁言
		{
			if (SendBuf.vip == 1)
			{
				system("clear");
				printf("请选择您想要禁言的人:\n");
				scanf("%s", SendBuf.toname);

				SendBuf.cmd = shutup;

				strcpy(SendBuf.username, name);

				if (strcmp(SendBuf.toname, name) == 0)
				{
					sleep(1);
					system("clear");
					printf("\t\t\t不可以禁言自己!\n");
					printf("\t\t\t请重新输入用户名!\n");
					break;
				}

				ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
				if (ret < 0)
				{
					perror("sendto_shutup1");
					exit(1);
				}
				printf("\n\n\t\t请稍等...\n");
				sleep(2);
			}

			else if (SendBuf.vip == 0)
			{
				printf("您需要开通会员才能禁言别人哦!\n");
			}

			break;
		}

		case 'h':  //踢人
		{
			if (SendBuf.vip == 1)	//这里就不注意对方是不是会员了 会员之间相互踢还是可以的
			{
				system("clear");
				printf("请选择您想要让他下线的人:\n");
				scanf("%s", SendBuf.toname);

				SendBuf.cmd = kick;

				strcpy(SendBuf.username, name);

				ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
				if (ret < 0)
				{
					perror("sendto_kick1");
					exit(1);
				}
				printf("\n\n\t\t请稍等...\n");
				sleep(2);
			}

			else if (SendBuf.vip == 0)
			{
				printf("您需要开通会员才能让别人下线哦!");
			}

			break;
		}

		case 'i':                  //查看聊天记录  
		{
			system("clear");
			char n[20];
			char filename1[50];
			char file1[2048];
			char kl;
			int fd1;
			int i = 0;
			printf("\n\n\n\n\n\n\t\t\t您想看和谁的聊天记录呢?\n");
			scanf("%s", n);
			SCAN_N();
			sprintf(filename1, "%s chat with %s.txt", name, n);
			fd1 = open(filename1, O_RDONLY, S_IRUSR | S_IWUSR);
			if (fd1 == -1)
			{
				system("clear");
				printf("\n\n\n\n\n\n\n\t\t\t您与%s还没有聊天记录!\n", n);
				break;
			}

			while (1)
			{
				memset(&kl, 0, sizeof(kl));
				ssize_t read_bytes = read(fd1, &kl, sizeof(kl));
				if (read_bytes == -1)
				{
					perror("read");
					return -1;
				}
				if (read_bytes == 0)
				{
					break;
				}
				file1[i] = kl;
				i++;
			}
			file1[i] = '\0';

			printf("\n%s\n", file1);

			sleep(3);

			break;
		}

		case 'j':                   //解禁  
		{
			char x[2];
			if (flag == 0)
			{
				system("clear");
				printf("\n\n\n\t\t\t您没有被禁言!\n");
			}
			else if (flag == 23)
			{
				if (SendBuf.vip == 0)
				{
					system("clear");
					printf("\n\n\n\n\t\t\t您还没有开通会员,请先开通会员!\n");
				}
				else if (SendBuf.vip == 1)
				{
					system("clear");
					printf("\n\n\n\n\t\t\t您想现在解禁吗!(y/n)\n");
					scanf("%s", x);
					SCAN_N();

					if (x[0] == 'y')
					{
						flag = 0;
						system("clear");
						printf("\n\n\n\t\t\t恭喜您成功解禁!\n");

					}
				}
			}
			break;
		}

		case 'k':   //下线
		{
			system("clear");
			SendBuf.cmd = quit;
			strcpy(SendBuf.username, name);
			ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
			if (ret < 0)
			{
				perror("sendto_quit1");
				exit(1);
			}
			sleep(1);
			return Exit;
		}

		case 'q':
			return Exit;


		default:
		{
			system("clear");
			printf("\n\n\n\n");
			printf("\n\n\t\t请输入a--z之间的选择!\n");
			sleep(2);
			break;
		}
		}
	}
}

//接收服务器发送的结果的接口函数
void *Recv_Server(void *arg)
{
	char q;
	int i;
	int length = sizeof(server_addr);
	while (1)
	{
		ret = recvfrom(*(int *)arg, &RecvBuf, sizeof(RecvBuf), 0, (struct sockaddr *)&server_addr, &length);
		if (ret < 0)
		{
			perror("recvfrom");
			exit(1);
		}

		switch (RecvBuf.result)
		{
		case(private_chat) :
		{
			printf("\t\t\t%s 给你发了一条消息:%s\n", RecvBuf.fromname, RecvBuf.message);
			memset(&RecvBuf.result, 0, sizeof(RecvBuf.result));
			break;
		}

		case(Send_success) :
		{
			system("clear");
			printf("\t\t\t发送成功\n");
			memset(&RecvBuf.result, 0, sizeof(RecvBuf.result));
			break;
		}

		case(Send_failure) :
		{
			system("clear");
			printf("\t\t\t发送失败,对方不在线\n");
			memset(&RecvBuf.result, 0, sizeof(RecvBuf.result));
			break;
		}

		case(Pchat_failure) :
		{
			system("clear");
			printf("\t\t\t对不起,对方不在线!\n");
			memset(&RecvBuf.result, 0, sizeof(RecvBuf.result));
			break;
		}

		case(group_chat) :
		{
			printf("\t\t\t%s 群发了一条消息:%s\n", RecvBuf.fromname, RecvBuf.message);
			memset(&RecvBuf.result, 0, sizeof(RecvBuf.result));
			break;
		}

		case(Gchat_failure) :
		{
			system("clear");
			printf("\t\t\t群聊失败!\n");
			memset(&RecvBuf.result, 0, sizeof(RecvBuf.result));
			break;
		}

		case(online) :
		{
			system("clear");
			printf("\t\t\t当前在线好友人数: %d\n", RecvBuf.num);
			for (i = 0; i < RecvBuf.num; i++)
			{
				printf("\t\t\t%s\n", RecvBuf.online_name[i]);
			}
			memset(&RecvBuf.result, 0, sizeof(RecvBuf.result));
			break;
		}

		case(face) :
		{
			char emoj1[20] = { 0 };
			switch (RecvBuf.p_f)
			{
			case '1':
			{
				strcpy(emoj1, "感动   ≧◇≦");
				printf("\t\t\t%s 给大家发了一个表情:%s\n", RecvBuf.fromname, emoj1);
				break;
			}
			case '2':
			{
				strcpy(emoj1, "无奈   ╮( ̄▽  ̄)╭");
				printf("\t\t\t%s 给大家发了一个表情:%s\n", RecvBuf.fromname, emoj1);
				break;
			}
			case '3':
			{
				strcpy(emoj1, "哭泣   T_T");
				printf("\t\t\t%s 给大家发了一个表情:%s\n", RecvBuf.fromname, emoj1);
				break;
			}
			case '4':
			{
				strcpy(emoj1, "惊讶   ⊙?⊙");
				printf("\t\t\t%s 给大家发了一个表情:%s\n", RecvBuf.fromname, emoj1);
				break;
			}
			case '5':
			{
				strcpy(emoj1, "喵 (= ̄ω ̄=)");
				printf("\t\t\t%s 给大家发了一个表情:%s\n", RecvBuf.fromname, emoj1);
				break;
			}
			case '6':
			{
				strcpy(emoj1, "害羞  (# ̄▽ ̄#)");
				printf("\t\t\t%s 给大家发了一个表情:%s\n", RecvBuf.fromname, emoj1);
				break;
			}


			}
			break;
		}

		case(face_failure) :
		{
			system("clear");
			printf("发送失败,没有该表情!\n");
			sleep(2);
			memset(&RecvBuf.result, 0, sizeof(RecvBuf.result));
			break;
		}

		case (send_useful) :
		{
			char ue[50];
			switch (RecvBuf.p_u)
			{
			case '1':
				strcpy(ue, "I see. 我明白了.");
				printf("\t\t\t%s给你发送了一句常用语:%s\n", RecvBuf.fromname, ue);

				break;

			case '2':
				strcpy(ue, "My god! 天哪!");
				printf("\t\t\t%s给你发送了一句常用语:%s\n", RecvBuf.fromname, ue);

				break;

			case '3':
				strcpy(ue, "3 No way! 不行!");
				printf("\t\t\t%s给你发送了一句常用语:%s\n", RecvBuf.fromname, ue);

				break;

			case '4':
				strcpy(ue, "Cheer up! 振作起来!");
				printf("\t\t\t%s给你发送了一句常用语:%s\n", RecvBuf.fromname, ue);

				break;

			case '5':
				strcpy(ue, "Good job! 做得好!");
				printf("\t\t\t%s给你发送了一句常用语:%s\n", RecvBuf.fromname, ue);

				break;

			case '6':
				strcpy(ue, "Bless you! 祝福你!");
				printf("\t\t\t%s给你发送了一句常用语:%s\n", RecvBuf.fromname, ue);

				break;

			case '7':
				strcpy(ue, "Thank you! 谢谢!");
				printf("\t\t\t%s给你发送了一句常用语:%s\n", RecvBuf.fromname, ue);
				break;
			}
			break;
		}

		case(vip_success) :
		{
			printf("\t\t\t恭喜您成功开通会员\n");
			sleep(2);
			break;
		}

		case(shutup) :
		{
			flag = 23;
			printf("\t\t\t%s已经把您禁言了!\n", RecvBuf.fromname);
			break;
		}

		case(shutup_success) :
		{
			printf("\t\t\t禁言成功!\n");
			sleep(2);
			break;
		}

		case(shutup_failure) :
		{
			printf("\t\t\t对方不在线,禁言失败!\n");
			break;
		}

		case(kick) :
		{
			out = 1;
			printf("\t\t\t您已经被%s踢出了聊天室,请重新登录!\n", RecvBuf.fromname);
			printf("\t\t\t输入q返回!\n");
			break;
		}

		case(kick_success) :
		{
			printf("\t\t\t踢人成功!\n");
			sleep(2);
			break;
		}

		case(kick_failure) :
		{
			printf("\t\t\t对方不在线,踢人失败!\n");
			break;
		}

		case(quit) :
		{
			system("clear");
			printf("您已经成功下线!\n");
			sleep(2);
			break;
		}

		}
	}
}

int main()
{
	int length = sizeof(server_addr);
	char choice[10] = { 0 };
	pthread_t tid;

	sockfd = socket(PF_INET, SOCK_DGRAM, 0);	//创建套接字
	if (-1 == sockfd)
	{
		perror("sockt");
		exit(1);
	}

	bzero(&server_addr, sizeof(server_addr));
	server_addr.sin_family = PF_INET;
	server_addr.sin_port = PORT;
	server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

	welcome();

	while (1)
	{
		show();

		scanf("%s", choice);

		switch (atoi(&choice[0]))
		{
		case 1:               //注册  
		{
			if (Register() == -12)
			{
				break;
			}
			else
			{
				ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
				if (ret < 0)
				{
					perror("sendto_register");
					exit(1);
				}
				bzero(&SendBuf, sizeof(SendBuf));

				ret = recvfrom(sockfd, &RecvBuf, sizeof(RecvBuf), 0, (struct sockaddr *)&server_addr, &length);

				if (ret < 0)
				{
					perror("recvfrom_register");
					exit(1);
				}

				if (RecvBuf.result == reg_success)
				{
					printf("\n\n\t\t\t恭喜您注册成功!\n");
				}

				else if (RecvBuf.result == existing)
				{
					printf("\n\n\t\t\t该账户已被注册!请重新注册!\n");
				}
				sleep(2);
				break;
			}
		}

		case 2:                               //登录
		{
			if (Login() == -14)
			{
				break;
			}
			else
			{
				ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
				if (ret < 0)
				{
					perror("sendto_login");
					exit(1);
				}
				bzero(&SendBuf, sizeof(SendBuf));

				ret = recvfrom(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&server_addr, &length);
				if (ret < 0)
				{
					perror("recvfrom_login");
					exit(1);
				}

				if (SendBuf.result == log_success)
				{
					printf("\n\n\t\t\t恭喜你登录成功!\n");
					strcpy(name, SendBuf.username);
					sleep(2);

					ret = pthread_create(&tid, NULL, (void *)Recv_Server, (void *)&sockfd); //起一个线程专门用来接收服务器发送给客户端的结果反馈
					if (ret < 0)
					{
						perror("pthread_create");
						exit(1);
					}
					pthread_detach(tid);

					ret = deal_login();
					if (ret == Exit)
					{
						break;
					}

				}

				else if (SendBuf.result == logged)
				{
					printf("\n\n\t\t\t账号已登录!\n");
				}

				else if (SendBuf.result == log_error)
				{
					printf("\n\n\t\t\t账号或密码错误,请重新登录!\n");
				}
			}
			break;
		}

		case 3:
		{
			bye();
			system("clear");
			exit(1);
			break;
		}

		default:
		{
			system("clear");
			printf("\n\n\n\n");
			printf("\n\n\t\t请输入1--3之间的选择!\n");
			sleep(2);
			break;
		}
		}
	}
	return 0;
}

server_function.h

#ifndef _SERVER_H_
#define _SERVER_H_

#include "chat.h"

struct info
{
	char username[20];          //用户名     
	char password[20];          //密码   
	int cmd;                    //提取操作类型  
	int result;                 //返回标记
	int port;                   //端口号
	char message[50];			//保存信息
	char toname[20];			//发送给谁
	char fromname[20];			//从谁那里接收
	char online_name[20][20];	//在线人员名单
	int num;
	int p_f;
	char emoj[20];				//表情
	int p_u;
	char useful[20];
	int vip;
	char question[50];
	char answer[50];
	char file_name[50];
	char file_content[2048];
};

struct node
{
	struct sockaddr_in client_addr;	//保存客户地址
	char name[20];					//记录客户姓名
	struct node *next;				//指向下一个用户
};
/*sockaddr_in 是internet环境下套接字的地址形式;;sockaddr_in在头文件#include<netinet/in.h>或#include <arpa/inet.h>中定义*/

typedef struct node Node;			//起别名 简化结构体 取名为 Node 用Node创建新结构体 存储客户信息
typedef Node *Lnode;				//同样 结构体取指针别名 对应的函数返回值是结构体类型

//注册函数
void register1();

//登录函数
void login(struct sockaddr_in tmp_addr);

//处理私聊
int deal_private(struct sockaddr_in tmp_addr);

//处理群聊 同上
int deal_group(struct sockaddr_in tmp_addr);

//显示在线人数
int deal_online();

//处理群发表情 同上
int deal_face(struct sockaddr_in tmp_addr);

//处理发送常用语  同上
int deal_useful(struct sockaddr_in tmp_addr);

//处理vip
int deal_vip(struct sockaddr_in tmp_addr);

//处理禁言	同上
int deal_shutup(struct sockaddr_in tmp_addr);

//处理踢人	同上
int deal_kick(struct sockaddr_in tmp_addr);

//处理下线
int deal_quit();

#endif

server_main.c

#include "serverfunction.h"
#include "chat.h"

struct info RecvBuf;				//接收方	的信息保存
struct info SendBuf;				//发送方	的信息保存

sqlite3 *ppdb = NULL;				//打开一个数据库实例
int ret;
int sockfd;
Lnode head = NULL;					//创建第一个节点

//注册函数
void register1()
{
	char sql[100] = { 0 };

	sprintf(sql, "insert into chat(username,password,vip) values('%s','%s','%d')", RecvBuf.username, RecvBuf.password, RecvBuf.vip);
	/*将数据插入到 sql数据库中,上述语句在执行完sprintf语句后,
	sql中保存的是INSERT语句字符串,可实现正确的插入。*/
	char *errmsg = NULL;		//保存 错误的原因
	int ret;
	ret = sqlite3_exec(ppdb, sql, NULL, NULL, &errmsg);					/*如果没有成功创建数据库实例则报错
																		(参考https://www.cnblogs.com/zfyouxi/p/5258589.html*/
	if (ret != SQLITE_OK)
	{
		perror("sqlite3_exec2");
		SendBuf.result = existing;										//账号已存在
		printf("%s is insert failure:%s\n\n", RecvBuf.username, errmsg);	//输出错因
		return;
	}

	//没有报错即成功
	printf("user insert success!yohoo~\n\n");
	SendBuf.result = reg_success;
}

//登录函数
void login(struct sockaddr_in tmp_addr)
{
	char sql[100] = { 0 };
	char **Result = NULL;			//返回记录,二维数组
	int nrow;						//查找出的	行数
	int ncolumn;					//查找出的	列数
	int ret;
	int i;

	sprintf(sql, "select username, password ,vip from chat where username = '%s' and password = '%s'", RecvBuf.username, RecvBuf.password);
	//查询语句 查看登录的用户信息
	ret = sqlite3_get_table(ppdb, sql, &Result, &nrow, &ncolumn, NULL);/* char **dbResult; 字符型的二重指针,
																	   将数据库里sqlite3_get_table()出来的数据以字符的方式给dbResult。*/
	if (ret != SQLITE_OK)												//未查询到表单数据
	{
		perror("sqlite3_get_table_login");
		return;
	}

	if (1 == nrow)								//如果chat表中已经有一个数据 同时数据的用户名和现在准备登录的用户名相同 则不允许登录
	{
		Lnode tmp = head->next;

		Lnode p = (Lnode)malloc(sizeof(Node));	//创建一个节点存储用户信息
		if (p == NULL)
		{
			printf("FAILURE!\n\n");
			return;
		}

		while (tmp != head)
		{
			if (!strcmp(tmp->name, Result[3]))
			{
				printf("您的账号已登录!\n\n");
				SendBuf.result = logged;
				return;
			}
			tmp = tmp->next;
		}

		SendBuf.result = log_success;

		strcpy(p->name, Result[3]);				//存储用户名字
		strcpy(SendBuf.username, Result[3]);
		SendBuf.vip = *(Result[5]) - 48;

		p->client_addr.sin_family = tmp_addr.sin_family;
		p->client_addr.sin_port = tmp_addr.sin_port;
		p->client_addr.sin_addr.s_addr = tmp_addr.sin_addr.s_addr;
		printf("记录到 %s 的端口号是 : %d\n", p->name, p->client_addr.sin_port);

		p->next = head->next;
		head->next = p;

		printf("%s 处于登录状态!\n\n", Result[3]);
	}

	else
	{
		SendBuf.result = log_error;
		printf("您的账号或密码错误,请重新登录!\n\n");
	}
}


//处理私聊
int deal_private(struct sockaddr_in tmp_addr)
{
	int postion = 0;								//创建一个标志位
	Lnode tmp = head->next;
	while (tmp != head)
	{
		if (strcmp(tmp->name, RecvBuf.toname) == 0)	//查询 找到 用户名和接收名 相同 发送信息过去
		{
			postion = 1;
			strcpy(SendBuf.message, RecvBuf.message);
			strcpy(SendBuf.fromname, RecvBuf.username);

			SendBuf.result = private_chat;
			ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp->client_addr, sizeof(tmp->client_addr));
			if (ret == -1)
			{
				perror("sendto_chat");
				exit(1);
			}
			break;
		}
		tmp = tmp->next;
	}

	if (postion)
	{
		SendBuf.result = Send_success;
		ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
		if (ret == -1)
		{
			perror("sendto_success");
			exit(1);
		}
	}
	else
	{
		SendBuf.result = Pchat_failure;
		ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
		if (ret == -1)
		{
			perror("sendto_failure");
			exit(1);
		}
	}
}

//处理群聊 同上
int deal_group(struct sockaddr_in tmp_addr)
{
	int postion = 0;
	Lnode tmp = head->next;
	while (tmp != head)
	{
		if (tmp->client_addr.sin_port != tmp_addr.sin_port)
		{
			postion = 1;

			SendBuf.result = group_chat;
			strcpy(SendBuf.fromname, RecvBuf.username);
			printf("%s\n", SendBuf.fromname);
			strcpy(SendBuf.message, RecvBuf.message);
			ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp->client_addr, sizeof(tmp->client_addr));
			if (ret < 0)
			{
				perror("sendto_group_chat");
				exit(1);
			}
		}
		tmp = tmp->next;
	}
	if (1 == postion)
	{
		SendBuf.result = Send_success;
		ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
		if (ret < 0)
		{
			perror("sendto_group_chat_success");
			exit(1);
		}
	}
	else
	{
		SendBuf.result = Gchat_failure;
		ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
		if (ret < 0)
		{
			perror("sendto_group_chat_failure");
			exit(1);
		}
	}
}

//显示在线人数
int deal_online()
{
	int i = 0;
	SendBuf.num = 0;
	Lnode tmp = head->next;
	while (tmp != head)
	{
		SendBuf.num++;
		strcpy(SendBuf.online_name[i], tmp->name);
		i++;
		tmp = tmp->next;
	}
	SendBuf.result = online;
}

//处理群发表情 同上
int deal_face(struct sockaddr_in tmp_addr)
{
	int postion = 0;
	Lnode tmp = head->next;
	while (tmp != head)
	{
		if (tmp->client_addr.sin_port != tmp_addr.sin_port)
		{
			postion = 1;

			SendBuf.result = face;
			strcpy(SendBuf.fromname, RecvBuf.username);
			SendBuf.p_f = RecvBuf.p_f;
			ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp->client_addr, sizeof(tmp->client_addr));
			if (ret < 0)
			{
				perror("sendto_face");
				exit(1);
			}
		}
		tmp = tmp->next;
	}
	if (1 == postion)
	{
		SendBuf.result = Send_success;
		ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
		if (ret < 0)
		{
			perror("sendto_face_success");
			exit(1);
		}
	}
	else
	{
		SendBuf.result = face_failure;
		ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
		if (ret < 0)
		{
			perror("sendto_face_failure");
			exit(1);
		}
	}
}

//处理发送常用语  同上
int deal_useful(struct sockaddr_in tmp_addr)
{
	int postion = 0;
	Lnode tmp = head->next;
	while (tmp != head)
	{
		if (strcmp(tmp->name, RecvBuf.toname) == 0)
		{
			postion = 1;
			SendBuf.result = send_useful;
			SendBuf.p_u = RecvBuf.p_u;
			strcpy(SendBuf.fromname, RecvBuf.username);
			ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp->client_addr, sizeof(tmp->client_addr));
			if (ret == -1)
			{
				perror("sendto_useful");
				exit(1);
			}
			break;
		}
		tmp = tmp->next;
	}

	if (postion)
	{
		SendBuf.result = Send_success;
		ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
		if (ret == -1)
		{
			perror("sendto_success");
			exit(1);
		}
	}
	else
	{
		SendBuf.result = Send_failure;
		ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
		if (ret == -1)
		{
			perror("sendto_failure");
			exit(1);
		}
	}
}

//处理vip
int deal_vip(struct sockaddr_in tmp_addr)
{
	char sql[100] = { 0 };

	sprintf(sql, "update chat set vip= %d where username = '%s';", RecvBuf.vip, RecvBuf.username);
	//更新数据库 信息即可

	ret = sqlite3_exec(ppdb, sql, NULL, NULL, NULL);
	if (ret != SQLITE_OK)
	{
		perror("sqlite3_exec");
		return;
	}

	SendBuf.vip = 1;				//VIP 标志位 置一
	SendBuf.result = vip_success;
	ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
	if (ret == -1)
	{
		perror("sendto_vip_failure");
		exit(1);
	}
	printf("%s 恭喜您成为了会员 ...\n", SendBuf.username);
	return 0;

}

//处理禁言	同上
int deal_shutup(struct sockaddr_in tmp_addr)
{
	Lnode tmp = head->next;
	int postion = 0;
	while (tmp != head)
	{
		if (strcmp(tmp->name, RecvBuf.toname) == 0)
		{
			postion = 1;
			SendBuf.result = shutup;
			strcpy(SendBuf.fromname, RecvBuf.username);
			ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp->client_addr, sizeof(tmp->client_addr));
			if (ret < 0)
			{
				perror("sendto_shutup");
				return;
			}

		}
		tmp = tmp->next;
	}
	if (postion)
	{
		SendBuf.result = shutup_success;
		ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
		if (ret < 0)
		{
			perror("sendto_shutup_success");
			return;
		}
	}
	else
	{
		SendBuf.result = shutup_failure;
		ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
		if (ret < 0)
		{
			perror("sendto_shutup_failure");
			return;
		}
	}
}

//处理踢人	同上
int deal_kick(struct sockaddr_in tmp_addr)
{
	int postion = 0;

	Lnode tmp = head->next;

	while (tmp != head)
	{
		if (strcmp(tmp->name, RecvBuf.toname) == 0)
		{
			postion = 1;

			SendBuf.result = kick;
			strcpy(SendBuf.fromname, RecvBuf.username);
			ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp->client_addr, sizeof(tmp->client_addr));
			if (ret < 0)
			{
				perror("sendto_kick");
				return;
			}

			Lnode p = tmp->next;	//借用指针将该处的人员删除 将后面的人员连接上来 代替此处人员
			tmp->next = p->next;
			free(p);

			printf("%s logged out...\n", RecvBuf.username);

			break;
		}
		tmp = tmp->next;
	}

	if (postion == 1)
	{
		SendBuf.result = kick_success;
		ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
		if (ret < 0)
		{
			perror("sendto_kick_success");
			exit(1);
		}
	}
	else
	{
		SendBuf.result = kick_failure;
		ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
		if (ret < 0)
		{
			perror("sendto_shutup_failure");
			exit(1);
		}
	}
}

//处理下线
int deal_quit()
{
	Lnode tmp = head;

	//1.如果是头结点
	if (tmp->next->next == head)
	{
		if (strcmp(tmp->next->name, RecvBuf.username) == 0)
		{

			Lnode p = tmp->next;		//借用指针将该处的人员删除 将后面的人员连接上来 代替此处人员
			tmp->next = p->next;
			free(p);

			printf("%s logged out...\n", RecvBuf.username);
			return;
		}
		tmp = tmp->next;
	}

	//2.不是头结点
	while (tmp->next != head)
	{
		if (strcmp(tmp->next->name, RecvBuf.username) == 0)
		{
			SendBuf.result = quit;

			Lnode l = tmp->next;
			tmp->next = l->next;
			free(l);

			printf("%s logged out...\n", RecvBuf.username);
			break;
		}
		tmp = tmp->next;
	}

	return 0;
}

int main()
{
	struct sockaddr_in server_addr;		//创建服务器	地址
	struct sockaddr_in client_addr;		//创建客户端	地址
	int length;
	int position;
	char sql[100] = { 0 };

	head = (Lnode)malloc(sizeof(Node));
	if (NULL == head)
	{
		printf("Malloc Failure!\n");
		return;
	}
	head->next = head;

	sockfd = socket(PF_INET, SOCK_DGRAM, 0);			//创建服务平台
	if (-1 == sockfd)
	{
		perror("socket");
		exit(1);
	}

	bzero(&server_addr, sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = PORT;
	server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");	//地址确定为 127.0.0.1

	ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));	//服务器地址绑定
	if (ret < 0)
	{
		perror("bind");
		exit(1);
	}

	ret = sqlite3_open("chat.db", &ppdb);		//如果存在 chat数据库 打开(可能是第二次执行程序的时候
	if (ret != SQLITE_OK)
	{
		perror("sqlite3_open");
		exit(1);
	}

	sprintf(sql, "create table if not exists chat (username text primary key, password text,vip integer);");
	/*		如果不存在chat数据库 就创建一个chat				*/
	ret = sqlite3_exec(ppdb, sql, NULL, NULL, NULL);
	if (ret != SQLITE_OK)
	{
		perror("sqlite3_exec1");
		exit(1);
	}

	while (1)
	{
		length = sizeof(client_addr);
		ret = recvfrom(sockfd, &RecvBuf, sizeof(RecvBuf), 0, (struct sockaddr *)&client_addr, &length);	//循环处理 接收信息
		if (ret < 0)
		{
			perror("recvfrom");
			exit(1);
		}

		printf("Recv From Client %d\n", client_addr.sin_port);		//输出(地址) 接收自哪个客户端

		printf("username is : %s\tpassword is : %s\n", RecvBuf.username, RecvBuf.password);

		switch (RecvBuf.cmd)			//根据接收到的 信息类型 执行相应的函数
		{
		case (reg) :                    //注册  
		{
			register1();
			ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&client_addr, sizeof(client_addr));	//打包信息
			if (ret < 0)
			{
				perror("sendto_server_register");
				exit(1);
			}

			break;
		}

		case (log_in) :                //登录
		{
			login(client_addr);
			ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&client_addr, sizeof(client_addr));
			if (ret < 0)
			{
				perror("sendto_server_log_in");
				exit(1);
			}
			break;
		}

		case (private_chat) :      //私聊
		{
			deal_private(client_addr);
			break;
		}

		case(group_chat) :           //群聊
		{
			deal_group(client_addr);
			break;
		}

		case(online) :             //查看在线人数
		{
			deal_online();
			ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&client_addr, sizeof(client_addr));
			if (ret == -1)
			{
				perror("sendto_online");
			}
			break;
		}

		case(face) :      //群发表情
		{
			deal_face(client_addr);
			break;
		}

		case(send_useful) :   //发送常用语
		{
			deal_useful(client_addr);
			break;
		}

		case(Vip) :              //开通会员
		{
			deal_vip(client_addr);
			break;
		}

		case(shutup) :           //禁言
		{
			deal_shutup(client_addr);
			break;
		}

		case(kick) :              //踢人
		{
			deal_kick(client_addr);
			break;
		}

		case(quit) :       //下线
		{
			deal_quit();
			ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&client_addr, sizeof(client_addr));
			if (ret == -1)
			{
				perror("sendto_quit");
			}
			break;
		}
		}
	}

	sqlite3_close(ppdb);		//最后关闭数据库

	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38313246/article/details/81625387