基于Linux系统的tcp协议的即时通信系统(聊天室)

这个聊天室完成了一些基础功能私聊、群聊、文件传送等基础功能,可以添加表情符号等其他功能。

头文件中的名称的定义可以换成枚举形式,会更加方便一点,我脑抽了就不改了。有空再完善代码规范和功能。


myhead.h

#ifndef _MYHEAD_H_
#define _MYHEAD_H_

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 


#define BUFFSIZE 50
#define MYPORT 6656
#define MYADDR "192.168.1.200"

/**功能选择**/
#define REG                  1
#define LOGIN                2
#define PRIVATE_CHAT         3
#define GROUP_CHAT           4
#define VIEW_FRIENDS         5
#define CORRECT_PIN_NUMBER   6
#define ADMINI_PRIVILEGE     7
#define SEND_OFFLINE_MSG     8
#define SEND_FILE            9
#define SIGN                 10
#define OFF_LINE             11
#define VIEW_USER_MSG        26
#define BECOME_VIP           39           //成为VIP

/**登陆注册**/
#define REG_SUCCESS          12
#define REG_FAIL             13
#define LOGIN_SUCCESS        14
#define LOGIN_FAIL           15
#define LOGIN_EXIT           16
/**创建链表**/
#define CREATE_NODE          17
/************/
#define PRIVATE_SUCCESS      18
#define PRIVATE_FAIL         19
#define GROUP_SUCCESS        20
#define VIEW_FRIENDS_SUCCESS 21
#define CORRECT_SUCCESS      22
#define CORRECT_FAIL         23
#define CORRECT_OLD          24           //用户原密码输入错误
#define OFF_LINE_SUCCESS     27
#define OFF_LINE_FAIL        28
/**权限**/
#define BAN                  29           //禁言
#define REMOVE               30           //解禁
#define KICK				 31			  //踢人
#define BAN_USER             32           //返回给被禁言的用户
#define REMOVE_USER          33           //返回给被解禁的用户
#define KICK_FAIL            34
#define BEEN_KICK            35
#define NO_POWER             36           //没有vip权限
#define SIGN_SUCCESS         37           
#define SEND_SUCCESS         38           //发送离线消息成功
#define VIP_SUCCESS          42
//#define BECOME_VIP           39           //成为VIP
#define SHOW_INFO            43
/**文件**/
#define FILE_SUCCESS         40
#define FILE_FAIL            41

typedef struct users        //用户信息:链表
{
	//struct regist *user;
	
	char username[20];      //用户名
	int clientfd;
	int power;              //1:禁言,0:未禁言
	struct users *next;
}user;

typedef struct regist       //注册
{
	int flag;               //注册登录标志符	
	int vip;                //会员用户          为1时具有会员权限,为0没有
	char username[20];      //用户名
	char password[20];      //密码
	char new_passwd1[20];   //新密码
	char new_passwd2[20];   //新密码验证
	char file[1024];        //文件
	char filename[20];      //文件名
	char sign[50];          //个性签名
//	int friend_num;         //好友数
//	int group_num;          //群组数
	char offline_msg[500];  //离线消息
	int action;		        //通过action表明是什么命令;
	char fromname[20];
	char toname[20];
	char time[20];          //时间
	
	char msg[500];          //消息内容
}client;


char my_getch()
{
	char temp = 0;
	temp = getchar();
	
}

#endif

server.c

#include "myhead.h"//server

void *read_msg_server(void *argc);
void register_client(int clientfd);
void login_client(int clientfd);
void private_chat(int clientfd);

sqlite3 *db = NULL;
char *errmsg = NULL;
char **result = NULL;
char sql[1024] = {0};

struct users *head = NULL;                    //创建用户信息的头结点

user userbuff;
client clientrecv;

int main()
{
	int socketfd = 0;
	int clientfd = 0;
	int ret = 0;
	
	struct sockaddr_in server_addr = {0};
	struct sockaddr_in client_addr = {0};
	
	socklen_t len = sizeof(struct sockaddr);
	pthread_t th;
	
	char recvbuff[20] = {0};
	int recvcnt = 0;
	
	char sendbuff[20] = {0};
	int sendcnt = 0;
	
	
	head = (struct users*)malloc(sizeof(struct users));
	if(head == NULL)
	{
		printf("malloc error\n");
	}
	//head->next = NULL;

	ret = sqlite3_open("chat.db",&db);         //建数据库
	if(ret != SQLITE_OK)
	{
		printf("数据库打开失败!");
	}

	sqlite3_exec(db,"create table account(username text primary key,password text,vip INTEGER,sign text,offline_msg text);",NULL,NULL,&errmsg);                                   //建注册信息表
	
	socketfd = socket(AF_INET,SOCK_STREAM,0);  //1.调用socket创建套接字
	if(socketfd == -1)
	{
		perror("socket");
		return -1;
	}
	printf("socket success...\n");  
	
	bzero(&server_addr,sizeof(server_addr));   //2.绑定:==》地址族,端口号,IP地址;下面就是赋值操作!
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(MYPORT);
	server_addr.sin_addr.s_addr = inet_addr(MYADDR);
	
	ret = bind(socketfd,(struct sockaddr *)&server_addr,sizeof(server_addr));
	if(ret == -1)
	{
		perror("bind");
		return -1;
	}
	printf("bind success...\n");
	
	ret = listen(socketfd,10);
	if(ret == -1)
	{
		perror("listen");
		return -1;
	}
	printf("listen success...\n");
	
	while(1)
	{
		clientfd = accept(socketfd,(struct sockaddr *)&client_addr,&len);
		if(clientfd == -1)
		{
			perror("accept");
			return -1;
		}
		printf("accept success... ");
		
		if(pthread_create(&th,NULL,read_msg_server,&clientfd) == -1)
		{
			perror("pthread_create");
			return -1;
		}
		pthread_detach(th);
		
	}
//	close(socketfd);
	sqlite3_free_table(result);
	slqite3_close(db);
	return 0;
}

void *read_msg_server(void *argc)
{
	struct users *p = head;
	int clientfd = *((int *)argc);		
	printf("read_msg_server:clientfd = %d\n",clientfd);
	
	int readcnt = 0;
	int writecnt = 0;

	while(1)
	{
		int login_flag = 0;
		memset(&clientrecv,0,sizeof(client));
		readcnt = read(clientfd,&clientrecv,sizeof(client));
		if(readcnt == -1)
		{
			perror("read_msg_client:read");
			return 0;
		}
		
		switch(clientrecv.action)
		{
			case 1:     //注册
			{
				register_client(clientfd);
				break;
			}
			case 2:     //登录
			{
				//login_client(clientfd);
				int i = 0;
				int j = 0;
				int nrow = 0; //行
				int ncolumn = 0; //列

				int flag = 0;
				int ret = 0;
				int readcnt =0;
				
				ret = sqlite3_get_table(db,"select * from account",&result,&nrow,&ncolumn,&errmsg);
				for(i = 1; i <= nrow; i++)
				{
					for(j = 0; j < ncolumn; j++)
					{
						if(strcmp(clientrecv.username,result[i*ncolumn]) == 0 && strcmp(clientrecv.password,result[i*ncolumn+ 1]) == 0)
						{
							flag = 1;  
							//strcpy(buff,clientrecv.username);
						}
					}
				}
				

				p = head;
				while(p->next != NULL)
				{	
					p = p->next;
					if(strcmp(p->username,clientrecv.username) == 0)
					{
						clientrecv.flag = LOGIN_EXIT;        //该用户已登录
						write(clientfd,&clientrecv,sizeof(client));
					}	
				}
				
				if(flag == 0)        //登录失败
				{
					clientrecv.flag = LOGIN_FAIL;
					write(clientfd,&clientrecv,sizeof(client));

				}
				else if(flag == 1)   //登录成功
				{
					clientrecv.flag = LOGIN_SUCCESS;
					write(clientfd,&clientrecv,sizeof(client));
				
					struct users *new = (struct users *)malloc(sizeof(struct users));
					strcpy(new->username,clientrecv.username);
					new->clientfd = clientfd;
					/*************************权限状态需要从数据库中读取**********************************/
					new->power = 0;   //未禁言状态            
					if(new == NULL)
					{
						printf("malloc error!\n");
						//return NULL;
					}
				/*	p = head;
					while(p->next != NULL)  //p不是尾结点
					{
						p = p->next;
					}
					*/p->next = new;
					new->next = NULL;
					//bzero(p,sizeof(struct users));
					
				}
				break;
			}
			case 3:                 //私聊
			{
				//private_chat(clientfd);
				
				p = head;
				int temp = 0;
				while(p->next !=NULL)
				{
					p = p->next;
					if(strcmp(p->username,clientrecv.toname) == 0)                                //存在该好友
					{
						temp = 1;
						//clientfd = p->clientfd;
						clientrecv.flag = PRIVATE_SUCCESS;
						//printf("m\n");
						printf("testing!!!\n");
						printf("%s(%d)send to%s(%d)",clientrecv.fromname,clientfd,clientrecv.toname,p->clientfd);
						write(p->clientfd,&clientrecv,sizeof(client));                            //发送给好友
						break;
					}
				}
				if(temp == 0)
				{
					clientrecv.flag = PRIVATE_FAIL;                                               //查无此人,回复给用户 
					write(clientfd,&clientrecv,sizeof(client));          
				}
			
				
				break;
			}
			case 4:                 //群聊
			{	
				p = head;
				while(p->next != NULL)
				{
					p = p->next;
					
					if(strcmp(p->username,clientrecv.username) == 0)
					{
						if(p->power == 1)
						{
							//memset(&clientrecv,0,sizeof(client));
							clientrecv.flag = NO_POWER;                                             //无发送权限,已被禁言
							writecnt = write(p->clientfd,&clientrecv,sizeof(client));
							if(writecnt == -1)
							{
								perror("view_friends");
								return 0;
							}
						}
						else if(p->power == 0)
						{
							p = head;
							while(p->next != NULL)
							{
								p = p->next;
						//		if(strcmp(p->username,clientrecv.username) != 0)		
								{
									clientrecv.flag = PRIVATE_SUCCESS;	
									writecnt = write(p->clientfd,&clientrecv,sizeof(client));          //发送给群
									if(writecnt == -1)
									{
										perror("group:write");
										return 0;
									}
								}									
							}
							printf("%s(%d)send :\n",clientrecv.fromname,clientfd);
						}
						break;
					}					
				}
				break;
			}
			case 5:                 //查看在线好友链表
			{
				p = head;
				char buff[20] = {0};
				strcpy(buff,clientrecv.username);
				
				while(p->next != NULL)
				{
					p = p->next;
					if(strcmp(p->username,buff) != 0)  //不显示自己的用户名,只显示好友列表
					{
						clientrecv.flag = VIEW_FRIENDS_SUCCESS;
						strcpy(clientrecv.username,p->username);
						writecnt = write(clientfd,&clientrecv,sizeof(client));
						if(writecnt == -1)
						{
							perror("view_friends");
							return 0;
						}
					}
				}
				break;
			}
			case 6:                 //修改密码
			{
				int i = 0;
				int j = 0;
				int nrow = 0; //行
				int ncolumn = 0; //列
				
				int ret = 0;
				int flag = 0;
				ret = sqlite3_get_table(db,"select * from account",&result,&nrow,&ncolumn,&errmsg);
				for(i = 1; i <= nrow; i++)
				{
					for(j = 0; j < ncolumn; j++)
					{
						if(strcmp(clientrecv.password,result[i*ncolumn+ 1]) == 0)//&&clientrecv.username == result[i*ncolumn]
						{
							flag = 1;  
						}
					}

				}
				if(flag == 1)                                                //用户原密码输入正确时
				{
					if(strcmp(clientrecv.new_passwd1,clientrecv.new_passwd2) == 0)   //新密码成功修改
					{
						sprintf(sql,"update account set password = '%s' where username = '%s';",clientrecv.new_passwd1,clientrecv.username);
						ret = sqlite3_exec(db,sql,NULL,NULL,&errmsg);
						if(ret != SQLITE_OK)                                //数据库中修改失败
						{
							clientrecv.flag = CORRECT_FAIL;
							write(clientfd,&clientrecv,sizeof(client));
						}
						else
						{
							clientrecv.flag = CORRECT_SUCCESS;
							write(clientfd,&clientrecv,sizeof(client));
						}	
					}
					else                                                              //新密码修改失败
					{
						clientrecv.flag = CORRECT_FAIL;
						write(clientfd,&clientrecv,sizeof(client));
					}
				}
				else if(flag == 0)                                          //用户原密码输入错误时
				{
					clientrecv.flag = CORRECT_OLD;
					write(clientfd,&clientrecv,sizeof(client));
				}
				break;
			}
			case 8:                 //发送离线消息(私聊转离线)
			{
				int ret = 0;
				p = head;
				int temp = 0;
				while(p->next != NULL)
				{
					p = p->next;
					if(strcmp(p->username,clientrecv.toname) == 0)  //用户在线
					{
						temp = 1;
					}					
				}
				if(temp == 0)
				{
					sprintf(sql,"insert into account (offline_msg) values('%s') where username = '%s';",clientrecv.msg,clientrecv.toname);
					ret = sqlite3_exec(db,sql,NULL,NULL,&errmsg);             //离线消息插入数据库
					clientrecv.flag = SEND_SUCCESS;
					write(clientfd,&clientrecv,sizeof(client));
				}
				break;
			}
			case 9:                 //发送文件
			{
				int ret = 0;
				p = head;
				int temp = 0;
				while(p->next != NULL)
				{
					p = p->next;
					if(strcmp(p->username,clientrecv.toname) == 0)
					{
						temp = 1;
						clientrecv.flag = FILE_SUCCESS;
						printf("%s(%d)send to%s(%d)",clientrecv.fromname,clientfd,clientrecv.toname,p->clientfd);
						write(p->clientfd,&clientrecv,sizeof(client));          //发送给好友
						
						break;
					}
				}
				if(temp = 0)
				{
					clientrecv.flag = FILE_FAIL;                                 //查无此人
					write(clientfd,&clientrecv,sizeof(client));
				}
			}
			case 10:                //修改个性签名
			{
				int i = 0;
				int j = 0;
				int nrow = 0; //行
				int ncolumn = 0; //列
				
				int ret = 0;
				int flag = 0;
				ret = sqlite3_get_table(db,"select * from account",&result,&nrow,&ncolumn,&errmsg);
				for(i = 1; i <= nrow; i++)
				{
					for(j = 0; j < ncolumn; j++)
					{
						if(strcmp(clientrecv.username,result[i*ncolumn+ 0]) == 0)
						{
							sprintf(sql,"update account set sign = '%s' where username = '%s';",clientrecv.sign,clientrecv.username);
							ret = sqlite3_exec(db,sql,NULL,NULL,&errmsg);
							if(ret != SQLITE_OK)                                //修改失败
							{
								return 0;                       //修改个签失败处理
							} 
							clientrecv.flag = SIGN_SUCCESS;
							
						}
					}
				}
				write(clientfd,&clientrecv,sizeof(client));
				break;
			}
			case 11:                //下线            
			{
				p = head;
				struct users *prev = NULL;
				while(p->next != NULL)
				{
					prev = p;        //prev保存p点前一个结点的地址
					p = p->next;
			
					if(strcmp(p->username,clientrecv.username) == 0)    //找到该用户
					{
						if(p->next == NULL)     //尾结点
						{
							prev->next = NULL;
							free(p);
							//p = NULL;        //NULL->next != NULL 出现段错误 
							clientrecv.flag = OFF_LINE_SUCCESS;
							writecnt = write(clientfd,&clientrecv,sizeof(client));
							if(writecnt == -1)
							{
								perror("view_friends");
								return 0;
							}
							break;
						}
						else
						{
							prev->next = p->next;
							free(p);
							//p = NULL;
							clientrecv.flag = OFF_LINE_SUCCESS;
							writecnt = write(clientfd,&clientrecv,sizeof(client));
							if(writecnt == -1)
							{
								perror("view_friends");
								return 0;
							}
							break;
						}
					}
					
				}
				clientrecv.flag = OFF_LINE_FAIL;      //下线失败
				writecnt = write(clientfd,&clientrecv,sizeof(client));
				if(writecnt == -1)
				{
					perror("view_friends");
					return 0;
				}
				break;
			}
			case 29:                //禁言
			{
				int i = 0;
				int j = 0;
				int nrow = 0; //行
				int ncolumn = 0; //列

				int flag = 0;
				int ret = 0;
				int readcnt =0;
				int temp = 0;
				
				ret = sqlite3_get_table(db,"select * from account",&result,&nrow,&ncolumn,&errmsg);
				for(i = 1; i <= nrow; i++)
				{
					for(j = 0; j < ncolumn; j++)
					{
						
						if(atoi(result[i*ncolumn + 2]) == 0 && strcmp(clientrecv.username,result[i*ncolumn]) == 0)     //无vip权限
						{
							clientrecv.flag = NO_POWER;     //无权限
							writecnt = write(clientfd,&clientrecv,sizeof(client));
							if(writecnt == -1)
							{
								perror("view_friends");
								return 0;
							}
							break;
						}
						else if(atoi(result[i*ncolumn + 2]) == 1 && strcmp(clientrecv.username,result[i*ncolumn]) == 0)  //有vip权限
						{
							flag = 1;
						}
					}
				}
		
				if(flag == 1)             //有禁言权限
				{
					p = head;
					while(p->next != NULL)
					{
						p = p->next;
						if(strcmp(clientrecv.toname,p->username) == 0)
						{
							p->power = 1;
							clientrecv.flag = BAN;
							writecnt = write(clientfd,&clientrecv,sizeof(client));
							

							
							if(writecnt == -1)
							{
								perror("view_friends");
								return 0;
							}
							clientrecv.flag = BAN_USER;
							writecnt = write(p->clientfd,&clientrecv,sizeof(client));
							if(writecnt == -1)
							{
								perror("view_friends");
								return 0;
							}
							break;
						}
					}
				}
				
				break;
			}
			case 30:                //解禁
			{
				int i = 0;
				int j = 0;
				int nrow = 0; //行
				int ncolumn = 0; //列

				int flag = 0;
				int ret = 0;
				int readcnt =0;
				
				ret = sqlite3_get_table(db,"select * from account",&result,&nrow,&ncolumn,&errmsg);
				for(i = 1; i <= nrow; i++)
				{
					for(j = 0; j < ncolumn; j++)
					{
						if(atoi(result[i*ncolumn + 2]) == 0 && strcmp(clientrecv.username,result[i*ncolumn]) == 0)    //无vip权限
						{
							clientrecv.flag = NO_POWER;     //无权限
							writecnt = write(clientfd,&clientrecv,sizeof(client));
							if(writecnt == -1)
							{
								perror("view_friends");
								return 0;
							}
						}
						else if(atoi(result[i*ncolumn + 2]) == 1 && strcmp(clientrecv.username,result[i*ncolumn]) == 0)  //有vip权限
						{
							flag = 1;
						}
					}
				}

				if(flag == 1)
				{
					p = head; 
					while(p->next != NULL)
					{
						p = p->next;
						if(strcmp(clientrecv.toname,p->username) == 0)
						{
							p->power = 0;      
							clientrecv.flag = REMOVE;
							writecnt = write(clientfd,&clientrecv,sizeof(client));				
							if(writecnt == -1)
							{
								perror("view_friends");
								return 0;
							}
							
							clientrecv.flag = REMOVE_USER;
							writecnt = write(p->clientfd,&clientrecv,sizeof(client));
							if(writecnt == -1)
							{
								perror("view_friends");
								return 0;
							}
							break;
						}
					}
				}
				
				break;
			}
			case 31:                //踢人
			{
				int i = 0;
				int j = 0;
				int nrow = 0; //行
				int ncolumn = 0; //列

				int flag = 0;
				int ret = 0;
				int readcnt =0;
				
				ret = sqlite3_get_table(db,"select * from account",&result,&nrow,&ncolumn,&errmsg);
				for(i = 1; i <= nrow; i++)
				{
					for(j = 0; j < ncolumn; j++)
					{
						if(atoi(result[i*ncolumn + 2]) == 0 && strcmp(clientrecv.username,result[i*ncolumn]) == 0)    //无vip权限
						{
							clientrecv.flag = NO_POWER;     //无权限
							writecnt = write(clientfd,&clientrecv,sizeof(client));
							if(writecnt == -1)
							{
								perror("view_friends");
								return 0;
							}
						}
						else if(atoi(result[i*ncolumn + 2]) == 1 && strcmp(clientrecv.username,result[i*ncolumn]) == 0)  //有vip权限
						{
							flag = 1;
						}
					}
				}
				
				if(flag == 1)
				{
					p = head;
					struct users *prev = NULL;
					while(p->next != NULL)
					{
						prev = p;        //prev保存p点前一个结点的地址
						p = p->next;
				
						if(strcmp(p->username,clientrecv.toname) == 0) 
						{
							if(p->next == NULL)     //尾结点
							{
								prev->next = NULL;
								free(p);
								//p = NULL;        //NULL->next != NULL 出现段错误 
								clientrecv.flag = KICK;
								writecnt = write(clientfd,&clientrecv,sizeof(client));
								if(writecnt == -1)
								{
									perror("view_friends");
									return 0;
								}
								clientrecv.flag = BEEN_KICK;
								writecnt = write(p->clientfd,&clientrecv,sizeof(client));
								if(writecnt == -1)
								{
									perror("view_friends");
									return 0;
								}
								break;
							}
							else
							{
								prev->next = p->next;
								free(p);
								//p = NULL;
								clientrecv.flag = KICK;
								writecnt = write(clientfd,&clientrecv,sizeof(client));
								if(writecnt == -1)
								{
									perror("view_friends");
									return 0;
								}
								break;
							}
						}
					}
					clientrecv.flag = KICK_FAIL;      //踢人失败
					writecnt = write(clientfd,&clientrecv,sizeof(client));
					if(writecnt == -1)
					{
						perror("view_friends");
						return 0;
					}
					break;	
				}
			}
			case 26:                //查看用户信息
			{
				int i = 0;
				int j = 0;
				int nrow = 0; //行
				int ncolumn = 0; //列

				int flag = 0;
				int ret = 0;
				int readcnt =0;
				
				ret = sqlite3_get_table(db,"select * from account",&result,&nrow,&ncolumn,&errmsg);
				for(i = 0; i<= nrow; i++)
				{
					for(j = 0; j < ncolumn; j++)
					{
						if(strcmp(clientrecv.username,result[i*ncolumn+ 0]) == 0)
						{
							strcpy(clientrecv.sign,result[i*ncolumn + 3]);
							clientrecv.vip = atoi(result[i*ncolumn + 2]);
							clientrecv.flag = SHOW_INFO;
							break;
						}
					}
				}
				write(clientfd,&clientrecv,sizeof(client));
				break;
				
			}
			case 39:                //注册会员
			{
				int i = 0;
				int j = 0;
				int nrow = 0; //行
				int ncolumn = 0; //列
				
				int ret = 0;
				int flag = 0;
				ret = sqlite3_get_table(db,"select * from account",&result,&nrow,&ncolumn,&errmsg);
				for(i = 1; i <= nrow; i++)
				{
					for(j = 0; j < ncolumn; j++)
					{
						if(strcmp(clientrecv.username,result[i*ncolumn+ 0]) == 0)
						{
							sprintf(sql,"update account set vip = '%d' where username = '%s';",clientrecv.vip,clientrecv.username);
							ret = sqlite3_exec(db,sql,NULL,NULL,&errmsg);
							if(ret != SQLITE_OK)                                //注册vip失败
							{
								perror("become vip");
								return 0;                       
							} 
							clientrecv.flag = VIP_SUCCESS;
							
						}
					}
				}
				write(clientfd,&clientrecv,sizeof(client));
				break;
			}
			default:
			{
				break;
			}
		}
	}
	close(clientfd);
}

/*******************注册********************/
void register_client(int clientfd)
{
	int ret = 0;
	int writecnt = 0;

	sprintf(sql,"insert into account(username,password,vip,sign,offline_msg)values('%s','%s',%d,'%s','%s');",clientrecv.username,clientrecv.password,clientrecv.vip,clientrecv.sign,clientrecv.offline_msg);
	ret = sqlite3_exec(db,sql,NULL,NULL,&errmsg);
	
	if(ret != SQLITE_OK)         //用户名已存在
	{
		clientrecv.flag = REG_FAIL;
	}
	else                          //成功创建新用户
	{
		clientrecv.flag = REG_SUCCESS;
	}	
	writecnt = write(clientfd,&clientrecv,sizeof(client));
	if(writecnt == -1)
	{
		perror("client:write");
		//return -1;
	}
}

client.c

#include "myhead.h"//client的主函数  :连接server并进行功能选择(注册,登录,退出)

void *read_msg_client(void *argc);
void menu(int socketfd);
void private_chat(int socketfd);
void group_chat(int socketfd);
void view_friends(int socketfd);
void correct_pin_number(int socketfd);
void off_line(int socketfd);
void admin_privilege(int socketfd);
void sign(int socketfd);
void send_offline_msg(int socketfd);
void become_vip(int socketfd);
void send_file(int socketfd);
void view_user_msg(int socketfd);;
  
sqlite3 *db = NULL;
char *errmsg = NULL;
char **result = NULL;
char sql[1024] = {0};

client clientsend;
client clientrecv;

char *my_time()
{
	time_t now;
	time(&now);
	return (ctime(&now));
}

int showscreen()
{
	int number = 0;

	int flag = 0;
	printf("                                \n");
	printf("********************************\n");
	printf("*           chatroom           *\n");
	printf("********************************\n");
	printf("*1.注册用户     2.用户登录     *\n");
	printf("*3.私聊         4.群聊         *\n");
	printf("*5.查看在线好友 6.修改密码     *\n");
	printf("*7.超级用户:禁言|解禁|踢人   *\n");
	printf("*8.发送离线消息 9.发送文件     *\n");
	printf("*10.个性签名    11.下线        *\n");
	printf("*12.查看用户信息13.注册会员    *\n");
	printf("********************************\n");

	printf("\n");
	printf("请输入选择的功能号:");
	flag = scanf("%d",&number);
	if(getchar() != '\n')
	{
		flag = 0;
	}
	while(flag != 1 || number < 0 || number > 13)
	{
		while(getchar() != '\n');
		printf("输入错误!请重新输入:");
		flag = scanf("%d",&number);
	}
	if(number >= 1 && number <= 13)
	{
		return number;
	}
}

int main()
{
	int socketfd = 0;
	int ret = 0;
	
	struct sockaddr_in server_addr;
	pthread_t th;
	
	int i = 0;
	int j = 0;
	int nrow = 0;         //行
	int ncolumn = 0;      //列
	
	int number = 0;       //用于注册登录界面
	int flag = 0;
	
	int writecnt = 0;
	int readcnt = 0;

	//client clientsend;
	//client clientrecv;
	
	socketfd = socket(AF_INET,SOCK_STREAM,0);
	if(socketfd == -1)
	{
		perror("socket");
		return -1;
	}
	printf("socket success...\n");
	
	bzero(&server_addr,sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(MYPORT);
	server_addr.sin_addr.s_addr = inet_addr(MYADDR);
	
	ret = connect(socketfd,(struct sockaddr *)&server_addr,sizeof(server_addr));
	if(ret == -1)
	{
		perror("connect");
		return -1;
	}
	printf("connect success...\n");
	
	while(1)
	{
		system("reset");
		printf("1.注册用户\n");
		printf("2.用户登录\n");
		printf("3.退出\n");
		printf("请输入选择的功能号:");
		//登录时:忘记密码,修改密码
		flag = scanf("%d",&number);
	    if(getchar() != '\n')
		{
			flag = 0;
		}
		while(flag != 1 || number < 0 || number > 3)
		{
			while(getchar() != '\n');
			printf("输入错误!请重新输入:");
			flag = scanf("%d",&number);
		}
		
		switch(number)
		{
			case 1:      //注册
			{ 
				int i = 0;
				int j = 0;
				int temp = 0;
				char secret[20] = {0};                              //用于密码的保密
				
				memset(&clientsend,0,sizeof(client));  
				clientsend.action = 1;
				printf("用户名:");     
				scanf("%s",clientsend.username);
				printf("密码:");
		/*		
				for(i = 0; secret[i] != '\n'; i++)
				{
					secret[i] = getchar();
					if(secret[i] == 10)
					{
						if(j == 0)
						{
							j++;
							continue;
						}
						break;
					}
					printf("*");
				}
				secret[i] = '\0';
				strcpy(clientsend.password,secret);
	*/			scanf("%s",clientsend.password);                          //考虑确认密码的实现
				printf("是否成为vip?(输入1:是,0:否): ");
				temp = clientsend.vip;
				scanf("%d",&temp);
				
				writecnt = write(socketfd,&clientsend,sizeof(client));    //发送给server
				if(writecnt == -1)
				{
					perror("client:write");
					return -1;
				}
				else
				{
					printf("正在验证中。。。\n");
				}
				memset(&clientrecv,0,sizeof(client)); 
				readcnt = read(socketfd,&clientrecv,sizeof(client));
				
				if(clientrecv.flag == REG_SUCCESS)
				{
					printf("注册成功!\n");
					getchar();
					getchar();
				}
				else if(clientrecv.flag == REG_FAIL)
				{
					printf("用户名不合法,注册失败!\n");
					getchar();
					getchar();
				}
				break;
			}
			case 2:        //登录
			{
				//memset(&clientsend,0,sizeof(client));
				clientsend.action = 2;
				printf("用户名:");
				scanf("%s",clientsend.username);
				printf("密码:");
				scanf("%s",clientsend.password);
				write(socketfd,&clientsend,sizeof(client));
				
				memset(&clientrecv,0,sizeof(client)); 
				read(socketfd,&clientrecv,sizeof(client));

				
	
				if(clientrecv.flag == LOGIN_SUCCESS)
				{
					printf("登录成功!\n");
					getchar();
					getchar();
					
					if(pthread_create(&th,NULL,read_msg_client,&socketfd) == -1)   //创建线程
					{
						perror("client:pthread_create");
						return -1;
					}
					
					menu(socketfd);
					
				}

				else if(clientrecv.flag == LOGIN_FAIL)
				{
					printf("用户名、密码不匹配,登录失败!\n");
					getchar();
					getchar();
				}
				else if(clientrecv.flag == LOGIN_EXIT)
				{
					printf("您已登录!\n");
					getchar();
					getchar();
				}
				break;
			} 
			case 3:
			{
				exit(0);
			}
			default:
			{
				break;
			}
		}
	}
	close(socketfd);
	
	return 0;
}

void *read_msg_client(void *argc)
{
	int socketfd = *((int *)argc); 
	
	//int readcnt = 0;
	
	
	
	while(1)
	{
		read(socketfd,&clientrecv,sizeof(client));	
		
		switch(clientrecv.flag)
		{
			case PRIVATE_SUCCESS:                  //私聊
			{
				printf("\n%s to you | %s :",clientrecv.fromname,my_time());
				printf("%s\n",clientrecv.msg);
				break;
			}
			case PRIVATE_FAIL:                     //私聊时查无此人
			{
				printf("查无此人。\n\n");
				break;
			}
			case GROUP_SUCCESS:                  //群聊
			{
				printf("\n%s send | %s :",clientrecv.fromname,my_time());
				printf("%s\n",clientrecv.msg);
				break;
			}
			case VIEW_FRIENDS_SUCCESS:            //查看在线好友链表
			{
				printf("\n好友:%s\n",clientrecv.username);
				break;
			}
			case CORRECT_SUCCESS:
			{
				printf("\n%s 修改密码成功!\n",clientrecv.username);
				break;
			}
			case CORRECT_FAIL:
			{
				printf("\n%s 新密码输入不一致!\n",clientrecv.username);
				break;
			}
			case CORRECT_OLD:
			{
				printf("\n%s 原密码输入错误!\n",clientrecv.username);
				break;
			}
			case OFF_LINE_SUCCESS:
			{
				exit(0);
			}
			case OFF_LINE_FAIL:
			{
				printf("\n%s 下线失败!\n",clientrecv.username);
				break;
			}
			case BAN:
			{
				printf("\n%s 已被成功禁言!\n",clientrecv.toname);
			}
			case BAN_USER:
			{
				printf("\n您已被禁言!\n");
				break;
			}
			case REMOVE:
			{
				printf("\n%s 已被成功解禁!\n",clientrecv.toname);
			}
			case REMOVE_USER:
			{
				printf("\n您已被解禁!\n");
				break;
			}
			case KICK:
			{
				printf("\n%s 已被成功踢出!\n",clientrecv.toname);
				break;
			}
			case KICK_FAIL:
			{
				printf("\n%s 未被踢出!\n",clientrecv.toname);
				break;
			}
			case BEEN_KICK:
			{
				exit(0);
			}
			case NO_POWER:
			{
				printf("\n您没有VIP权限,不能进行该操作!\n");
				//sleep(5);
				break;
			}
			case SIGN_SUCCESS:
			{
				printf("\n成功修改个性签名!\n");
				//sleep(5);
				break;
			}
			case SEND_SUCCESS:
			{
				printf("\n离线消息发送成功\n");
				break;
			}
			case FILE_SUCCESS:
			{
				char ch = '0';
				int ret = 0;
				
				printf("\n%s send a file to you | %s :",clientrecv.fromname,my_time());
				printf("filename:%s\n",clientrecv.filename);
			/*	printf("你要接收该文件吗?  y/n");
				scanf(" %c",&ch);
				while(ch != 'y' && ch != 'n')
				{
					while(getchar() != '\n');
					printf("输入错误!请重新输入:");
					scanf("%ch",&ch);
				}
				if(ch == 'y')                                              //接收文件
			*/	{
					int fd = 0;
					fd = open("new.txt",O_CREAT|O_RDWR|S_IRUSR|S_IWUSR);
					if(fd < 0)
					{
						perror("open");
						//return -1;
					}
					ret = write(fd,clientrecv.file,strlen(clientrecv.file));//从file数组中提取数据写入文件
					printf("%s\n",clientrecv.file);
					if(ret < 0)
					{
						perror("write");
						//return -1;
					}
					break;
				}
/*				else if(ch == 'n')                                          //拒收文件
				{
					break;
				}
*/			}
			case FILE_FAIL:
			{
				printf("\n查无此人\n");
				break;
			}
			case VIP_SUCCESS:
			{
				printf("\n您已获得vip。\n");
				break;
			}
			case SHOW_INFO:
			{
				printf("\n用户名:%s\n",clientrecv.username);
				//while(getchar() != '\0');
				printf("个性签名:%s\n",clientrecv.sign);
				printf("是否为vip会员:");
				if(clientrecv.vip == 1)
				{
					printf("是\n");
				}
				else
				{
					printf("不是\n");
				}
				break;
			}
			default:
			{
				break;
			}
		}
	}
}


void menu(int socketfd)
{
	int number = 0;
	
	while(1)
	{		
		system("reset");
		number = showscreen();
		system("reset");

		switch(number)
		{
			case 3:
			{
				private_chat(socketfd);          //私聊
				break;
			}
			case 4:
			{
				group_chat(socketfd);             //群聊
				break;
			}
			case 5:
			{
				view_friends(socketfd);           //查看在线好友链表
				break;
			}
			case 6:
			{
				correct_pin_number(socketfd);      //修改密码
				break;
			}
			case 7:
			{
				admin_privilege(socketfd);         //管理员权限:禁言|解禁|踢人
				break;
			}
			case 8:
			{
				send_offline_msg(socketfd);         //发送离线消息
				break;
			}
			case 9:
			{
				send_file(socketfd);                //发送文件
				break;
			}
			case 10:
			{
				sign(socketfd);                     //修改个性签名
				break;
			}
			case 11:
			{
				off_line(socketfd);                 //下线
				//printf("成功退出!\n");
				//exit(0);
			}
			case 12:
			{
				view_user_msg(socketfd);            //查看用户信息
				break;
			}
			
			
			case 13:                                //会员
			{
				become_vip(socketfd);
				break;
			}
			default:
			{
	//			printf("输入错误,请输入正确的功能号。\n");
	//			getchar();
	//			getchar();
				break;
			}
		}
	}
}
/******************私聊*******************************/
void private_chat(int socketfd)
{ 
	char buff[500] = {0};
	
	clientsend.action = PRIVATE_CHAT;
	
	printf("请输入你要私聊的用户名:\n");
	scanf("%s",buff);
	strcpy(clientsend.toname,buff);
	strcpy(clientsend.fromname,clientsend.username);
	while(strcmp(clientsend.toname,clientsend.username) == 0)
	{
	    while(getchar() != '\n');
		printf("私聊对象不能为本身,请重新输入:\n");
		scanf("%s",buff);
		strcpy(clientsend.toname,buff);
	}
	
	while(1)
	{

		printf("请输入发送的内容:\n");                        //我发送的信息内容
		//scanf("%s",buff);
		//strcpy(clientsend.msg,buff);
		scanf("%s",clientsend.msg);
		
		if(strcmp(clientsend.msg,"end") == 0 || strcmp(clientsend.toname,"end") == 0 )
		{			
			break;	
		}
	
		write(socketfd,&clientsend,sizeof(client));
	}

}

/*********************群聊*****************************/
void group_chat(int socketfd)    //群聊
{
	char buff[500] = {0};
	while(1)
	{
		clientsend.action = GROUP_CHAT;
		strcpy(clientsend.fromname,clientsend.username);
		printf("请输入发送的内容:\n");
		scanf("%s",buff);
		strcpy(clientsend.msg,buff);
		write(socketfd,&clientsend,sizeof(client));
		
		if(strcmp(clientsend.msg,"end") == 0 || strcmp(clientsend.toname,"end") == 0)
		{			
			break;	
		}
	}

	
}

/********************查看在线好友链表********************************/
void view_friends(int socketfd)     //好友为0时,好友个数
{
	char ch = '0';
	while(1)
	{
		//int writecnt = 0;
		clientsend.action = VIEW_FRIENDS;
		write(socketfd,&clientsend,sizeof(client));
	
		printf("请输入 'q' 返回主界面 :");
		scanf("%c",&ch);
		while(ch != 'q')
		{
			while(getchar() != '\n');
			printf("输入错误!  请输入 'q' 返回主界面 :");
			scanf(" %c",&ch);
		}
		if(ch == 'q')
		{
			break;
		}
	}
		
}

/**********************修改密码***********************************/
void correct_pin_number(int socketfd)   
{
	while(1)
	{
		char buff[20] = {0};
		char ch = '0';
		clientsend.action = CORRECT_PIN_NUMBER;
		
		printf("请输入原密码 : ");
		scanf("%s",buff);
		strcpy(clientsend.password,buff);
		memset(&buff,0,sizeof(char));
		printf("请输入新密码 : ");
		scanf("%s",buff);
		strcpy(clientsend.new_passwd1,buff);
		memset(&buff,0,sizeof(char));
		printf("请再次输入新密码 : ");
		scanf("%s",buff);
		strcpy(clientsend.new_passwd2,buff);
		write(socketfd,&clientsend,sizeof(client));
		
		printf("请输入 'q' 返回主界面 :");
		scanf("%c",&ch);
		while(ch != 'q')
		{
			while(getchar() != '\n');
			printf("输入错误!  请输入 'q' 返回主界面 :");
			scanf(" %c",&ch);
		}
		if(ch == 'q')
		{
			break;
		}
		
	}
}

/*********************下线*****************************/
void off_line(int socketfd)
{
	char ch = '0';
	clientsend.action = OFF_LINE;
	printf("确认下线吗?   y/n :  \n");
	scanf("%c",&ch);
	while(ch != 'n' && ch != 'y')
	{
		while(getchar() != '\n');
		printf("输入错误! 请输入 y/n:\n");
		scanf(" %c",&ch);
	}
	if(ch == 'y')
	{
		write(socketfd,&clientsend,sizeof(client));
	}
	else if(ch == 'n')
	{
		printf("返回主界面。\n");
	}
	
}


/****************会员权限************************/
void admin_privilege(int socketfd)
{
	while(1)
	{
		int number = 0;
		int flag = 0;
		char buff[20] = {0};
		char ch = '0';
		
		//clientsend.action = ADMINI_PRIVILEGE;
		printf("1.禁言\n");
		printf("2.解禁\n");
		printf("3.踢人\n\n");
		printf("请输入你选择的命令(数字):\n");
		//scanf("&d",&number);
		flag = scanf("%d",&number);
		if(getchar() != '\n')
		{
			flag = 0;
		}
		while(flag != 1 || number < 1 || number > 3)
		{
			while(getchar() != '\n');
			printf("输入错误!请重新输入:");
			flag = scanf("%d",&number);
		}
		if(number == 1)
		{
			clientsend.action = BAN;
		}
		else if(number == 2)
		{
			clientsend.action = REMOVE;
		}
		else if(number == 3)
		{
			clientsend.action = KICK;
		}
		
		printf("请输入对象:\n");
		scanf("%s",buff);
		strcpy(clientsend.toname,buff);
		write(socketfd,&clientsend,sizeof(client));
		
		printf("\n是否继续? 请输入y/n:\n");
		scanf(" %c",&ch);
		while(ch != 'n' && ch != 'y')
		{
			while(getchar() != '\n');
			printf("输入错误! 请输入y/n:\n");
			scanf(" %c",&ch);
		}
		if(ch == 'n')
		{
			break;
		}
	}
}


/*********************发送文件************************/
void send_file(int socketfd)
{
	char buff[1024] = {0};
	char ch = 0;
	int i = 0;
	int ret = 0;
	int temp = 0;
	
	clientsend.action = SEND_FILE;
	
	printf("请输入你要发送文件的对象:\n");
	scanf("%s",buff);
	strcpy(clientsend.toname,buff);
	strcpy(clientsend.fromname,clientsend.username);
	while(strcmp(clientsend.toname,clientsend.username) == 0)
	{
	    while(getchar() != '\n');
		printf("发送文件对象不能为本身,请重新输入:\n");
		scanf("%s",buff);
		strcpy(clientsend.toname,buff);
	}
	printf("请输入发送的文件名:\n");
	scanf("%s",clientsend.filename);
	
	int fd = 0;;
	fd = open(clientsend.filename,O_RDONLY,S_IRUSR|S_IWUSR);
	if(fd < 0)
	{
		printf("该文件不存在!");
		//exit(-1);
		temp = 1;
	}
	if(temp == 0)
	{
		while(1)          //从文件中读取数据到file数组中
		{
			memset(&ch,0,sizeof(ch));
			ssize_t read_bytes = read(fd,&ch,sizeof(ch));
			if(read_bytes == -1)
			{
				perror("read");
				//return -1;
			}
			if(read_bytes == 0)        //读完退出循环
			{
				break;
			}
			clientsend.file[i] = ch;
			i++;
		}
		clientsend.file[i] = '\0';
		ret = write(socketfd,&clientsend,sizeof(client));
		if(ret = -1)
		{
			perror("write");
			//return -1;
		}
	}
	
}


/********************个性签名**********************/
void sign(int socketfd)
{
	while(1)
	{
		char ch = '0';
		char buff[50] = {0};
		clientsend.action = SIGN;
		
		printf("请输入你的个性签名:\n");
		scanf("%s",buff);
		strcpy(clientsend.sign,buff);
		write(socketfd,&clientsend,sizeof(client));
		
		printf("请输入 'q' 返回主界面 :");
		scanf("%c",&ch);
		while(ch != 'q')
		{
			while(getchar() != '\n');
			printf("输入错误!  请输入 'q' 返回主界面 :");
			scanf(" %c",&ch);
		}
		if(ch == 'q')
		{
			break;
		}
		
	}
}

/*****************发送离线消息*************************/
void send_offline_msg(int socketfd)
{	
	char buff[500] = {0};
	
	while(1)
	{
		clientsend.action = SEND_OFFLINE_MSG;
	
		printf("请输入你要发送离线消息的用户名:\n");
		scanf("%s",buff);
		strcpy(clientsend.toname,buff);
		strcpy(clientsend.fromname,clientsend.username);
		while(strcmp(clientsend.toname,clientsend.username) == 0)
		{
		    while(getchar() != '\n');
			printf("发送离线消息对象不能为本身,请重新输入:\n");
			scanf("%s",buff);
			strcpy(clientsend.toname,buff);
		}
		printf("请输入发送的内容:\n");                        //我发送的信息内容
		scanf("%s",buff);
		strcpy(clientsend.msg,buff);
		write(socketfd,&clientsend,sizeof(client));

		if(strcmp(clientsend.msg,"end") == 0 || strcmp(clientsend.toname,"end") == 0)
		{			
			break;	
		}
	}
}

/*********************查看用户信息*************************/
void view_user_msg(int socketfd)
{
	clientsend.action = VIEW_USER_MSG;
	
	write(socketfd,&clientsend,sizeof(client));
}

/********************注册会员***********************/
void become_vip(int socketfd)
{
	
	char buff[20] = {0};
	char ch = '0';
	int writecnt = 0;
	while(1)
	{
		clientsend.action = BECOME_VIP;
		
		printf("是否成为vip?(输入y:是,n:否):\n");
		scanf(" %c",&ch);
		while(ch != 'y' && ch != 'n')
		{
			while(getchar() != '\n');
			printf("输入错误!请重新输入:");
			scanf("%ch",&ch);
		}
		if(ch == 'y')
		{
			clientsend.vip = 1;
			writecnt = write(socketfd,&clientsend,sizeof(client));
			if(writecnt = -1)
			{
				perror("write ");
				return 0;
			}
		}
		else if(ch == 'n')
		{
			break;
		}
	}
}





你可能感兴趣的:(c)