Select 实现网络聊天室功能 (服务器端)

服务器端:

ChatRoom.h

#ifndef  _CHATROOM_H_H
#define  _CHATROOM_H_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sqlite3.h>
#include <pthread.h>
#include <time.h>
#include <sys/stat.h>
#include <fcntl.h>



#define  TRUE     1
#define  FALSE    2
#define  SUCCESS  3
#define  FAILURE  4
#define  PORT     8888

#define  REGISTER               100
#define  REG_SUCCESS            101
#define  LOGIN                  102
#define  LOG_SUCCESS            103
#define  LOG_FAILURE            104
#define  OnLine                 105
#define  NoOnLine               106
#define  Online                 107
#define  PrivateChat            108
#define  OFFLINE                109
#define  GroupChat              110
#define  ChatVip                111
#define  ShutUp                 112
#define  NoShutup               113
#define  SHUTUP                 114
#define  IsChatVip              115
#define  NoChatVip              116
#define  IsGroupShutup          117
#define  NoGroupShutup          118
#define  Kick                   119
#define  KickSuccess            120    
#define  KickFailure            121
#define  KickOk                 122
#define  KickNoOk               123
#define  Expression             124

struct user
{
	char id[20];
	char password[20];
	char username[20];
	char toname[20];
	int Tofd;                             //文件描述符
    int cmd;
    char online[20][20]	;
    int n;	                              //记录在线人数
	char buf[100];                        //聊天内容 
	int vip ;
    int speak;
	int find;
	char ep;                             

};

struct linknode
{
	struct user User;
	struct linknode *next;
};



void Register(struct user *U);
void Login(struct user *U);
int isOnLine(struct linknode *List, struct user *User);
void ListInsert(struct linknode *list, struct user *User);
void TraverList(struct linknode*list, struct user *User);
void ChatRoom(int chatfd, struct user recvbuf, struct user USER);
void DeleteList(struct linknode *list, struct user *User);
void TraverId(struct linknode *list, struct user User, sqlite3 *db);
void TraverFriend(struct linknode *list, struct user User, sqlite3 *db);
void gettime();
void DealVip(struct user User, sqlite3 *db);
void Shut_up(struct user User, sqlite3 *db);
void DealKick(struct linknode *list, struct user User, sqlite3 *db);
char *nowtime();
void ExpressionShow();
void des_ep(struct user User);

#endif
		


Server.c

#include <stdio.h>
#include "ChatRoom.h"

struct linknode *UserList;

struct user RecvBuf = {0};

int isOnLine(struct linknode *list, struct user *User)
{

		struct linknode *p =list->next;
		while (p != NULL && strcmp(p->User.id, User->id) != 0 )
		{
			
			p = p->next;
		}
		if (p == NULL)
		{
			return NoOnLine;
		}
		return OnLine;

}

void ListInsert(struct linknode *list, struct user *User)
{
	    struct linknode *p = list;
		struct linknode*node = (struct linknode*)malloc(sizeof(struct linknode));
		
		strcpy(node->User.id, User->id); 
		strcpy(node->User.username, User->username);
		node->User.Tofd = User->Tofd;
		
		node->next = p->next;
		p->next = node;
		
}

/*void copyUser(struct user *User1, struct user *User2)
{
	strcpy((*User1).username, (*User2).username);
}*/

 void TraverList(struct linknode *list, struct user *User)
{
    
	int j = 0;
	if (list == NULL)
	{
		return ;
	}
	struct linknode *p  = list->next;
	while (p)
	{
		
	    strcpy(RecvBuf.online[j], p->User.username);
		j++;
		p = p->next;
	}
    RecvBuf.n = j; 
	send(User->Tofd, &RecvBuf, sizeof(RecvBuf), 0);

	memset(&RecvBuf, 0 , sizeof(RecvBuf));
    
	
}

void TraverId(struct linknode *list, struct user User, sqlite3 *db)
{
	int ret;
	char sql[300] = {0};
	char *errmsg = NULL;
	char **dbResult = NULL;
	int nRow, nCol;
	

	if (list == NULL)
	{
		return ;
	}
	struct linknode *p = list->next;
	
	while(p)
	{
		if (User.Tofd == p->User.Tofd)
		{
			strcpy(User.username, p->User.username);             //拷贝自己的名字
			break;
		}
		p = p->next;
	}
	
	sprintf(sql, "select speak from message where username = '%s';", User.username);
	ret  = sqlite3_get_table(db, sql, &dbResult, &nRow, &nCol, &errmsg);
	if (ret != SQLITE_OK)
	{
		perror("sqlite3_get_table");
		exit(1);
	}

	if (*dbResult[1]-48 == 1)
	{	User.find = SHUTUP;
		ret = send(User.Tofd, &User, sizeof(User), 0);
		if (ret < 0)
		{
			perror("send");
			exit(1);
		}
	}
	else
	{
		p = list->next;
		while(p)
		{	
			if (!strcmp(p->User.username, User.toname ))
			{	
				User.find = NoShutup;
				ret = send(p->User.Tofd, &User, sizeof(User), 0);     //从链表中找出你想发送人的文件描述符
				if (ret < 0)
				{
					perror("send");
					exit(1);
				}
		
				break;		
			}
	
			p = p->next;

		}


	}
}

void DeleteList(struct linknode*list, struct user *User)
{
	struct linknode *p = list;
	struct linknode *tmp  ;

	if (p == NULL)
	{
		return;
	}

	while(p->next != NULL)
	{
		
		if (strcmp(p->next->User.id, User->id) == 0)       //根据帐号判断是否下线
		{
			tmp = p->next;
	        p->next = tmp->next;
	        free(tmp);
			break;
		}
		p = p->next;
	}


}




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

	sqlite3 *ppdb;
	char sql[300] = {0};
	char **dbResult = NULL;
	int nRow, nCol;
	char *errmsg = NULL;

	UserList = (struct linknode*)malloc(sizeof(struct linknode));
	UserList->next = NULL;
    

	ret = sqlite3_open("message.db", &ppdb);                //打开或创建数据库
    if (ret != SQLITE_OK)
	{
		perror("sqlite3_open");
		exit(1);

	}
	sprintf(sql,"create table if not exists message (id text, password text, username text, vip integer, speak integer);");
	ret = sqlite3_exec(ppdb, sql, NULL, NULL, NULL);
	if (ret != SQLITE_OK)
	{
		perror("sqlite3_execl");
		exit(1);
	}

	sockfd = socket(PF_INET, SOCK_STREAM, 0);              // socket 建立连接,不用于发送消息
	if (sockfd < 0)
	{
		perror("sockfd");
		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 = inet_addr("192.168.0.128");

	ret = bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));    //绑定信息
	if (ret < 0)
	{
		perror("bind");
		exit(1);
	}

	
	ret = listen(sockfd, 20);                  //监听
	if (ret < 0)
	{
		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);
		if (-1 == ret)
		{
			perror("select");
			exit(1);
		}

		if(FD_ISSET(sockfd, &TmpFd))                            //检测
		{
			length = sizeof(client_addr);
			fd[i] = accept(sockfd, (struct sockaddr *)&client_addr, &length);
			if (fd[i] < 0)
			{
				perror("accept");
				exit(1);
			}

			printf("Accept  %d  Port  %d\n",fd[i], client_addr.sin_port);          //打印客户端端口号

			FD_SET(fd[i], &ReadFd);
			j = 0;
			Tem = fd[0];
			while(fd[j])
			{
				if (Tem < fd[j])
				{
					Tem = fd[j];
				}
				j++;
			}
			MaxFd = Tem;
			i++;
		}
		else
		{
			for(j = 0; j < i; j++)
			{
				if (FD_ISSET(fd[j], &TmpFd))
				{
					ret = recv(fd[j], &RecvBuf, sizeof(RecvBuf), 0);            //接收客户端的请求
					
					if (ret < 0)
					{
						perror("recv");
						exit(1);
					}
                        
					switch(RecvBuf.cmd)
					{

    
						case REGISTER:                        //注册用户信息
						{
							RecvBuf.Tofd = fd[j];
							
							memset(sql, 0, sizeof(sql));
                                                
							sprintf(sql, "insert into message (id, password, username, vip, speak) values ('%s', '%s', '%s', %d, %d);", RecvBuf.id, RecvBuf.password, RecvBuf.username, RecvBuf.vip,RecvBuf.speak);

							ret = sqlite3_exec(ppdb, sql, NULL, NULL, NULL);
							if (ret != SQLITE_OK)
							{			
								perror("sqlite3_exec2");
								exit(1);
							}
							RecvBuf.cmd = REG_SUCCESS;
                            send(RecvBuf.Tofd, &RecvBuf, sizeof(RecvBuf), 0);
						    memset(&RecvBuf, 0 , sizeof(RecvBuf));
							break;
						}

						case LOGIN:                                                //登录信息
						{
							RecvBuf.Tofd = fd[j];
						    memset(sql, 0, sizeof(sql));	
							sprintf(sql, "select * from message where id = '%s' and password = '%s';", RecvBuf.id, RecvBuf.password);
							ret = sqlite3_get_table(ppdb, sql,&dbResult, &nRow, &nCol, &errmsg);
							if (ret != SQLITE_OK)
							{
								perror("sqlite3_get_table");
							 	exit(1);
							} 
							
							
							int i;
							for (i = 0; i < (nRow + 1) * nCol; i++)
							{
								if (strcmp(dbResult[i],RecvBuf.id) == 0 && strcmp(dbResult[i+1], RecvBuf.password) == 0)
								{   
									ret = isOnLine(UserList, &RecvBuf);
									if (ret == OnLine)
									{
										RecvBuf.cmd = OnLine;
										break;
									}
									strcpy(RecvBuf.username,dbResult[i+2]);                        
									ListInsert(UserList, &RecvBuf);
									RecvBuf.cmd = LOG_SUCCESS;

									break;
								}

							}
	                         	send(RecvBuf.Tofd, &RecvBuf, sizeof(RecvBuf), 0);
								memset(&RecvBuf, 0, sizeof(RecvBuf));
								break;
						}

						case Online:
							{
								RecvBuf.Tofd = fd[j];
								TraverList(UserList, &RecvBuf);
								memset(&RecvBuf, 0, sizeof(RecvBuf));
								break;
							}
					    case PrivateChat:
							{
								RecvBuf.Tofd = fd[j];
								TraverId(UserList, RecvBuf, ppdb);
								memset(&RecvBuf, 0, sizeof(RecvBuf));
								break;
							}
						case GroupChat:
							{
								RecvBuf.Tofd = fd[j];
								TraverFriend(UserList, RecvBuf, ppdb);
								memset(&RecvBuf, 0, sizeof(RecvBuf));
								break;
							}
						
						case ChatVip:
							{
								RecvBuf.Tofd = fd[j];
								DealVip(RecvBuf, ppdb);
								memset(&RecvBuf, 0, sizeof(RecvBuf));
								break;
							}
						case Kick:
							{
								RecvBuf.Tofd = fd[j];
								DealKick(UserList, RecvBuf, ppdb);
								memset(&RecvBuf, 0, sizeof(RecvBuf));
								break;
							}
						case ShutUp:
							{
								RecvBuf.Tofd = fd[j];
								Shut_up(RecvBuf, ppdb);
								memset(&RecvBuf, 0, sizeof(RecvBuf));
								break;
							}
						case Expression:
							{
								RecvBuf.Tofd = fd[j];
								Send_expression(UserList, RecvBuf, ppdb);
								memset(&RecvBuf, 0, sizeof(RecvBuf));
								break;
							}
						case OFFLINE:
							{
								RecvBuf.Tofd = fd[j];
								DeleteList(UserList, &RecvBuf);
								memset(&RecvBuf, 0, sizeof(RecvBuf));

								FD_CLR(fd[j], &ReadFd);
								close(fd[j]);
								break;
							}
					}	
				}
			}
		}

	}



	return 0;
}


TestServer.c

#include <stdio.h>
#include "ChatRoom.h"

void TraverFriend(struct linknode *list, struct user User, sqlite3 *db)
{
	int ret;
	char sql[300] = {0};
	char *errmsg = NULL;
	char **dbResult = NULL;
	int nRow, nCol;

	if (NULL == list)
	{
		return;
	}

	struct linknode *p = list->next;

	while(p)
	{
		if (p->User.Tofd == User.Tofd)
		{
			strcpy(User.username, p->User.username);
			break;
		}
		p = p->next;
	}
	sprintf(sql, "select speak from message where username = '%s';", User.username);
	ret = sqlite3_get_table(db, sql, &dbResult, &nRow, &nCol, &errmsg);
	if (ret != SQLITE_OK)
	{
		perror("sqlite3_get_table");
		exit(1);
	}

	if (*dbResult[1] - 48 == 1)
	{   User.find = IsGroupShutup;
		ret = send(User.Tofd, &User, sizeof(User), 0);
		if (ret < 0)
		{
			perror("send");
			exit(1);
		}
	}
	else
	{
		p = list->next;
		while(p)
		{
			if (strcmp(p->User.username, User.username) != 0)
			{	
				User.find = NoGroupShutup;
				ret = send(p->User.Tofd, &User, sizeof(User), 0);
				if (ret < 0)
				{
					perror("send");
					exit(1);
				}

			}
			p = p->next;
		}

	}

}


void DealVip(struct user User, sqlite3 *db)
{
	int ret;
	char sql[300] = {0};
	char *errmsg = NULL;
    char **dbResult = NULL;
	int nRow, nCol;

	sprintf(sql, "select vip from message where username = '%s';",User.username);
	ret = sqlite3_get_table(db, sql, &dbResult, &nRow, &nCol, &errmsg);
	if (ret != SQLITE_OK)
	{
		perror("sqlite3_get_table");
		exit(1);
	}

	if (*dbResult[1]-48 == 0)
	{
		User.vip = 1;
		memset(sql, 0, sizeof(sql));
		sprintf(sql, "update message set vip = %d where username = '%s';", User.vip, User.username);
		ret = sqlite3_exec(db, sql, NULL, NULL, &errmsg);
		if (ret != SQLITE_OK)
		{
			perror("sqlite3_exec");
			exit(1);
		}

		ret = send(User.Tofd, &User, sizeof(User), 0);
		if (ret < 0)
		{
			perror("send");
			exit(1);
		}
		
	}
	else
	{
		ret = send(User.Tofd, &User, sizeof(User), 0);
		if (ret < 0)
		{
			perror("send");
			exit(1);
		}

	}


}

void Shut_up(struct user User, sqlite3 *db)
{
	int ret;
	char sql[300] = {0};
	char *errmsg = NULL;
    char **dbResult = NULL;
	int nRow, nCol;

	sprintf(sql, "select vip from message where username = '%s';", User.username);
	ret = sqlite3_get_table(db, sql, &dbResult, &nRow, &nCol, &errmsg);
	if (ret != SQLITE_OK)
	{
		perror("sqlite3_get_table");
		exit(1);
	}

	if (*dbResult[1] -  48 == 0)
	{
		User.find = NoChatVip;
		ret = send(User.Tofd, &User, sizeof(User), 0);
		if (ret < 0)
		{
			perror("send");
			exit(1);
		}
	}
	else
	{
		User.speak = 1;
		User.find = IsChatVip;
		memset(sql, 0, sizeof(sql));
		sprintf(sql, "update message set speak = %d where username = '%s';", User.speak, User.toname);
		ret = sqlite3_exec(db, sql, NULL, NULL, &errmsg);
		if (ret != SQLITE_OK)
		{
			perror("sqlite3_exec");
			exit(1);
		}

		ret = send(User.Tofd, &User, sizeof(User), 0);
		if (ret < 0)
		{
			perror("send");
			exit(1);
		}

	}	

}

void DealKick(struct linknode *list, struct user User, sqlite3 *db)
{
		int ret;
		struct linknode *p = list;
		struct linknode *tmp;
		
		char sql[200] = {0};
		char *errmsg = NULL;
		char **dbResult = NULL;
		int nRow, nCol;

		if (p == NULL)
		{
			return ;
		}

		sprintf(sql, "select vip from message where username = '%s';", User.username);
		ret = sqlite3_get_table(db, sql, &dbResult, &nRow, &nCol, &errmsg);
		if (ret != SQLITE_OK)
		{
			perror("sqlite3_get_table");
			exit(1);
		}

		if (*dbResult[1] - 48 == 0)
		{
			User.find = KickFailure;
			ret = send(User.Tofd, &User, sizeof(User), 0);
			if (ret < 0)
			{
				perror("send");
				exit(1);
			}
		}
		else
		{
			while(p->next)
			{
				if (!strcmp(p->next->User.username, User.toname))    //要特别注意条件里的p->next是否成立
				{
					User.find = KickSuccess;
					ret = send(User.Tofd, &User, sizeof(User), 0);
					if (ret < 0)
					{
					perror("send");
					exit(1);
					}

					User.find = KickOk;
					User.Tofd = p->next->User.Tofd;
					ret = send(User.Tofd, &User, sizeof(User), 0);
					if (ret < 0)
					{
						perror("send");
						exit(1);
					}

					tmp = p->next;
					p->next = tmp->next;
					free(tmp);
					break;
				}
				p = p->next;
			}
			if (p->next == NULL)
			{
				User.find = KickNoOk;
				ret = send(User.Tofd, &User, sizeof(User), 0);
				if (ret < 0)
				{
					perror("send");
					exit(1);
				}
			}

		}

	

}

void Send_expression(struct linknode *list, struct user User, sqlite3 *db)
{
	int ret;
	char sql[200] = {0};
	char *errmsg = NULL;
    char **dbResult = NULL;
	int nRow, nCol;

	if (list == NULL)
	{
		return ;
	}
	struct linknode *p = list->next;

	sprintf(sql, "select speak from message where username = '%s';", User.username);
	ret = sqlite3_get_table(db, sql, &dbResult, &nRow, &nCol, &errmsg);
	if (ret != SQLITE_OK)
	{
		perror("sqlite3_get_table");
		exit(1);
	}
	if(*dbResult[1] - 48 == 1)
	{
		User.find = SHUTUP;
		ret = send(User.Tofd, &User, sizeof(User), 0);
		if (ret < 0)
		{
			perror("send");
			exit(1);
		}
	}
	else
	{
		p = list->next;
		while(p)
		{
			if (!strcmp(p->User.username, User.toname))
			{
				User.find = NoShutup;
				ret = send(p->User.Tofd, &User, sizeof(User), 0);
				if (ret < 0)
				{
					perror("send");
					exit(1);
				}
				break;
			}
			p = p->next;
		}
	}

}



  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值