服务器端:
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
#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;
}
}
}