#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
#include <sqlite3.h>
#define PORTNUMBER 9994
#define MAXNUM 10
#define OK 1
#define ERROR 0
typedef int Elementtype;
typedef int Status;
//与客户端一致的结构体
typedef struct client
{
Elementtype id;
Elementtype flag;
Elementtype case_num;//服务器进行功能选择
Elementtype case_numnext;//登录成功聊天功能选择
char name[100];
char password[150];
//char content_c[1024];//接收客户端发送消息
}Client_message;
//定义一个服务器的结构体
typedef struct server
{
Elementtype i_s;
Elementtype num_s[10];
Elementtype case_snum;//服务器发送进行的功能 0注册成功,1登录失败,2普通用户登录,3管理员登录
Elementtype id__s; //4私聊时查找ID有人,5私聊查找ID没人,6查询在线人数
char name_s[100];
char password_s[150];
//char content_s[1024];//服务器发送的消息缓存区
}Server_message;
//链表结构体
typedef struct node
{
int id_l;
int fd_l;
struct node *next;
}linkedlist;
Client_message msg_accept;//定义一个全局的结构体名字,接收客户端的结构体
Server_message msg_send;//定义一个全局的结构体名字,发送服务器的结构体
linkedlist *list;
//链表函数
linkedlist *createlinkedlist();
int getcount(linkedlist *list);
//void insert1(linkedlist *list, int id, int fd);
linkedlist *insert2(linkedlist *list, int id, int fd);
int queryfd(linkedlist *list, int id);
int queryid(linkedlist *list, int fd);
void printf_list(linkedlist *list);
linkedlist *dellinkedlist(linkedlist *list, int fd);
void *func(void * arg);
int newfd;//定义一个全局整形的套接字
int main(int argc, char *argv[])
{
system("clear");
//message msg_accept;
int ret;
printf("服务器正在初始化......\n");
sleep(2);
int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == socket_fd)
{
perror("建立通信失败");
exit(1);
}
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORTNUMBER);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
printf("初始化服务器成功......\n");
printf("正在启动服务器......\n");
sleep(2);
if (-1 == bind(socket_fd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr)))
{
perror("绑定地址失败");
exit(2);
}
if(-1 == listen(socket_fd, MAXNUM))//最大监听用户人数为10
{
perror("监听失败");
exit(3);
}
printf("服务器启动成功......\n");
sqlite3 *db;
ret = sqlite3_open("./server.db", &db);//打开数据库
if(ret != SQLITE_OK)
{
printf("打开数据库失败\n");
}
printf("打开数据库成功......\n");
printf("正在等待客户端的连接......\n");
ret = sqlite3_close(db);
if(ret != SQLITE_OK)
{
printf("关闭数据库失败\n");
}
//创建一个单链表
list = createlinkedlist();
pthread_t pid;
while(1)
{
struct sockaddr_in client_addr;
int length = sizeof(struct sockaddr);
newfd = accept(socket_fd, (struct sockaddr *)(&client_addr), &length);
if (-1 == newfd)
{
perror("接收失败");
exit(1);
}
printf("客服端%d连上了服务器......\n",newfd);
pthread_create(&pid,NULL,(void*)func,(void*)newfd);
}
//close(newfd);
return 0;
}
void *func(void * arg)
{
int newfd = (int)arg;//强转为套接字类型
char sendbuff[1024] = {0};//服务器发送信息
char buff[1024] = {0};//把套接字先缓存到的区域
int ret;
static int num = 1000;//用作ID
// message *msg_accept = (message *)arg ;//把arg强转为结构体
while(1)
{
ret = read(newfd, buff,1024);
if(-1 == ret)
{
perror("读取错误");
exit(1);
}
memset(&msg_accept,0,sizeof(msg_accept));//清空结构体
memcpy(&msg_accept,buff,sizeof(msg_accept));//把收到的信息转换为结构体
//printf("msg_accept.name = %s\t,msg_accept.password = %s\n",msg_accept.name,msg_accept.password);
//printf("msg_accept.case_num = %d\n",msg_accept.case_num);
switch(msg_accept.case_num)
{
case 1 : //客户请求注册
{
printf("---------------------------------------------\n");
printf("客户端需要注册的名字为: %s 密码 :%s\n",msg_accept.name,msg_accept.password);
printf("---------------------------------------------\n");
sqlite3 *db;
char *errmsg;
ret = sqlite3_open("server.db",&db);
if(ret != SQLITE_OK)
{
perror("打开数据库失败");
exit(2);
}
char sql_insert[1024] = {0};
sprintf(sql_insert,"insert into server(id ,name,password) values(%d,'%s','%s');",num,msg_accept.name,msg_accept.password);
printf("----------------------以下信息已进入数据库-----------------------\n");
printf("%s\n",sql_insert);
printf("-----------------------------------------------------------------\n");
ret = sqlite3_exec(db,sql_insert,NULL,NULL,&errmsg);
if(ret != SQLITE_OK)
{
perror("插入数据库失败");
exit(3);
}
ret = sqlite3_close(db);
if(ret != SQLITE_OK)
{
perror("关闭数据库失败");
exit(4);
}
msg_send.case_snum = 0;
msg_send.id__s = num;
num++;
memset(sendbuff,0,1024);
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd ,sendbuff, 1024);
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
break;
}
case 2: //客户请求登录
{
printf("---------------------------------------------\n");
printf("有客户需要登录, 登录ID:%d 密码:%s \n",msg_accept.id,msg_accept.password);
printf("---------------------------------------------\n");
sqlite3 *db;
char *errmsg;
int row;
int column;
char**result;
ret = sqlite3_open("server.db",&db);
if(ret != SQLITE_OK)
{
perror("打开数据库失败");
exit(2);
}
char sql_client[1024] = {0};
sprintf(sql_client,"select id,password from server where id = %d and password = '%s';",msg_accept.id,msg_accept.password);
ret = sqlite3_get_table(db, sql_client, &result, &row, &column, &errmsg);
if(ret != SQLITE_OK)
{
perror("查询数据库失败");
exit(3);
}
int i;
int j;
printf("-------查询结果如下--------\n");
for(i = 1;i <= row;i++)
{
for(j = 0;j < column;j++)
{
printf("%s|",result[i * column + j]);
}
printf("\n");
}
printf("---------------------------\n");
ret = sqlite3_close(db);
if(ret != SQLITE_OK)
{
perror("关闭数据库失败");
exit(4);
}
if(column == 0)
{
printf("你登录的信息有误,请重新登录.\n");
msg_send.case_snum = 1;
memset(sendbuff,0,1024);
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd ,sendbuff, 1024);
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
break;
}
else//登录成功
{
printf("恭喜你登录成功.\n");
if(msg_accept.id == 1000)//管理员登录
{
memset(sendbuff,0,1024);
printf("管理员上线.\n");
msg_send.case_snum = 3;//管理登录成功后发送到客户端的指令
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd ,sendbuff, 1024);
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
}
else //普通用户登录成功
{
memset(sendbuff,0,1024);
printf("普通用户上线.\n");
msg_send.case_snum = 2;//普通用户登录成功后发送到客户端的指令
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd ,sendbuff, 1024);
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
}
//插入信息到链表
list = insert2(list, msg_accept.id, newfd);
printf("现在在线人物信息 :\n");
printf_list(list);
printf("在线人数为:%d\n", getcount(list));
while(1)
{
memset(buff,0,1024);
ret = read(newfd,buff,1024);
if(-1 == ret)
{
perror("读取失败");
exit(1);
}
memcpy(&msg_accept,buff,sizeof(msg_accept));
switch(msg_accept.case_numnext)
{
case 1://查看当前人数
{
/*
char str[1024] = {0};
sprintf(str,"当前在线人数为: %d\n",count);
ret = write(newfd,str,1024);
if(-1 == ret)
{
perror("写入人数失败");
exit(2);
}
*/
int count = getcount(list);//用链表查看当前的人数
memset(sendbuff ,0 ,1024);
msg_send.id__s = count;//用作id_s临时记录下在线的人数
printf("count = %d\n",msg_send.id__s);
msg_send.case_snum = 6;//查询在线人数
//memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd ,sendbuff, 1024);
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
sleep(1);
linkedlist *h = list;
int temp = 0;
while(h != NULL)
{
msg_send.num_s[temp] = h -> id_l;
temp++;
h = h -> next;
}
msg_send.i_s = temp;
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd ,sendbuff, 1024);
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
break;
}
case 2: //发送私聊
{
int send_newfd = queryfd(list, msg_accept.id);//查询私聊人物的FLAG
//是否有此人
// printf("查到的客户端是: %d\n", send_newfd);
int id_client = queryid(list,newfd);//查询发送消息人物的ID
//printf("id_client = %d\n",id_client);//打印他的ID
if(send_newfd != 0)//有此人
{
printf("客户端%d 私聊客户端%d 消息为 : %s\n",newfd,send_newfd,msg_accept.name);
memset(sendbuff ,0 ,1024);
msg_send.id__s = send_newfd;//用作id_s临时记录下客户端的FLAG
msg_send.case_snum = 4;//查询有这个ID
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd ,sendbuff, 1024);
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
memset(sendbuff,0,1024);
strcpy(msg_send.name_s,msg_accept.name);
msg_send.case_snum = 7;//用于发送私聊消息的指令
msg_send.id__s = id_client;//用于记录发送人的ID
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(send_newfd,sendbuff,1024);//发送给要私聊的人
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
memset(sendbuff,0,1024);
msg_send.case_snum = 8;//用于发聩消息发送成功了指令
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd,sendbuff,1024);//发送给发起私聊的人
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
}
else
{
printf("没有这个ID\n");
memset(sendbuff ,0 ,1024);
msg_send.case_snum = 5;//没有这个ID
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd ,sendbuff, 1024);
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
}
break;
}
case 3: //发送群聊
{
int id_client = queryid(list,newfd);//查询发送群聊消息人物的ID
printf("客户端%d发起了群聊,内容是:%s\n",newfd,msg_accept.name);
int i;
linkedlist *h = list;
//把在线人数都遍历出来
for(i = 0; i < getcount(list); i++)
{
if(h -> fd_l != newfd)
{
memset(sendbuff, 0, 1024);
strcpy(msg_send.name_s,msg_accept.name);//复制群聊的消息到服务器的结构体里面
msg_send.case_snum = 9;//用于发送群聊消息的指令
msg_send.id__s = id_client;//用于记录发送人的ID
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(h -> fd_l, sendbuff, 1024);
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
}
h = h -> next;
}
memset(sendbuff,0,1024);
msg_send.case_snum = 10;//用于发聩消息发送成功了指令
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd,sendbuff,1024);//发送给发起群聊的人
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
break;
}
case 4: //客户请求发送文件
{
int ret;
int accept_newfd = queryfd(list, msg_accept.id);//查询文件要发送到人物的FLAG
int id_send = queryid(list,newfd);//查询发送文件的ID
printf("客户端%d请求发送文件给客户端%d,文件名是: %s\n",newfd,accept_newfd,msg_accept.name);
memset(sendbuff,0,1024);
//先把名字发给要接受文件的人
msg_send.case_snum = 18;
msg_send.id__s = id_send;
strcpy(msg_send.name_s,msg_accept.name);
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(accept_newfd,sendbuff,1024);
if(-1 == ret)
{
perror("写入失败\n");
exit(1);
}
//把内容发给要接受文件的人
while(1)
{
char buffer_file[1024];
memset(buffer_file, 0, 1024);//清空缓存
if(recv(newfd, buffer_file, 1024, 0) < 0)
{
perror("接收失败");
exit(1);
}
printf("内容是 :\n");
printf("%s\n",buffer_file);
if(send(accept_newfd, buffer_file, 1024, 0) < 0)
{
perror("发送失败");
exit(1);
}
if(0 == strncmp(buffer_file, "END", 3))
{
break;
}
}
//把发送成功的消息发聩给发送者
memset(sendbuff,1024,0);
msg_send.case_snum = 19;
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd,sendbuff,1024);
if(-1 == ret)
{
perror("写入失败\n");
exit(1);
}
break;
}
case 5: //客户请求下线
{
printf("客户端%d请求下线\n",newfd);
list = dellinkedlist(list, newfd);
printf_list(list);
memset(sendbuff,0,1024);
msg_send.case_snum = 11;//用于发聩消息发送成功了指令
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd,sendbuff,1024);//发送给发起请求下线的人
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
//break;
goto out;
}
case 6://禁言
{
printf("管理员请求禁言,禁言的ID是%d\n",msg_accept.id);
memset(sendbuff, 0, 1024);
int jinyan_newfd = queryfd(list,msg_accept.id);//查询被禁言人的客户端
msg_send.case_snum = 12;
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(jinyan_newfd,sendbuff,1024);//发送给被禁言的人
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
//禁言成功反馈给管理员
msg_send.case_snum = 13;
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd,sendbuff,1024);//发送给被禁言的人
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
break;
}
case 7://解禁
{
printf("管理员请求解禁,解禁的ID是%d\n",msg_accept.id);
memset(sendbuff, 0, 1024);
int jiejin_newfd = queryfd(list,msg_accept.id);//查询被禁言人的客户端
msg_send.case_snum = 14;
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(jiejin_newfd,sendbuff,1024);//发送给被禁言的人
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
//解禁成功反馈给管理员
msg_send.case_snum = 15;
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd,sendbuff,1024);//发送给管理员
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
break;
}
case 8://踢人下线
{
printf("管理员请求踢人,被踢人的ID是%d\n",msg_accept.id);
memset(sendbuff, 0, 1024);
int tiren_newfd = queryfd(list,msg_accept.id);//查询被踢人的客户端
msg_send.case_snum = 16;
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(tiren_newfd,sendbuff,1024);//发送给被踢的人
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
//踢人成功反馈给管理员
msg_send.case_snum = 17;
memset(sendbuff, 0, 1024);
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd,sendbuff,1024);//发送给管理员
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
break;
}
}
}
break;
}
break;
}
case 3:
{
printf("客户端%d请求退出\n",newfd);
goto outroom;
}
}//switch
out:
printf("-----------\n");
}//while(1)
outroom:
close(newfd);
}
linkedlist *createlinkedlist()
{
linkedlist *h;
h = NULL;
return h;
}
linkedlist *dellinkedlist(linkedlist *list, int fd)
{
linkedlist *p = list -> next;
linkedlist *h = list;
if(list -> fd_l == fd)
{
free(h);
return list -> next;
}
else
{
while(p -> fd_l != fd)
{
p = p -> next;
h = h -> next;
}
h -> next = p -> next;
free(p);
return list;
}
}
linkedlist *insert2(linkedlist *list, int id, int fd)
{
linkedlist *head, *p;
head = list;
p = (linkedlist *)malloc(sizeof(linkedlist));
if(head == NULL)
{
head = p;
p -> next = NULL;
}
else
{
p -> next = head;
head = p;
}
p -> id_l = id;
p -> fd_l = fd;
return head;
}
int getcount(linkedlist *list)
{
linkedlist *h = list;
int count = 0;
while(h != NULL)
{
count++;
h = h -> next;
}
return count;
}
int queryid(linkedlist *list, int fd)
{
linkedlist *p, *h;
h = list;
while(h != NULL)
{
if(fd == h -> fd_l)
{
return h -> id_l;
}
h = h -> next;
}
}
int queryfd(linkedlist *list, int id)
{
linkedlist *h = list;
while(h != NULL)
{
if(id == h -> id_l)
{
return h -> fd_l;
}
h = h -> next;
}
return 0;
}
void printf_list(linkedlist *list)
{
linkedlist *h = list;
while(h != NULL)
{
printf("在线人物的ID为 :%d FLAG : %d\n", h ->id_l, h -> fd_l);
h = h -> next;
}
printf("\n");
}
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
#include <sqlite3.h>
#define PORTNUMBER 9994
#define MAXNUM 10
#define OK 1
#define ERROR 0
typedef int Elementtype;
typedef int Status;
//与客户端一致的结构体
typedef struct client
{
Elementtype id;
Elementtype flag;
Elementtype case_num;//服务器进行功能选择
Elementtype case_numnext;//登录成功聊天功能选择
char name[100];
char password[150];
//char content_c[1024];//接收客户端发送消息
}Client_message;
//定义一个服务器的结构体
typedef struct server
{
Elementtype i_s;
Elementtype num_s[10];
Elementtype case_snum;//服务器发送进行的功能 0注册成功,1登录失败,2普通用户登录,3管理员登录
Elementtype id__s; //4私聊时查找ID有人,5私聊查找ID没人,6查询在线人数
char name_s[100];
char password_s[150];
//char content_s[1024];//服务器发送的消息缓存区
}Server_message;
//链表结构体
typedef struct node
{
int id_l;
int fd_l;
struct node *next;
}linkedlist;
Client_message msg_accept;//定义一个全局的结构体名字,接收客户端的结构体
Server_message msg_send;//定义一个全局的结构体名字,发送服务器的结构体
linkedlist *list;
//链表函数
linkedlist *createlinkedlist();
int getcount(linkedlist *list);
//void insert1(linkedlist *list, int id, int fd);
linkedlist *insert2(linkedlist *list, int id, int fd);
int queryfd(linkedlist *list, int id);
int queryid(linkedlist *list, int fd);
void printf_list(linkedlist *list);
linkedlist *dellinkedlist(linkedlist *list, int fd);
void *func(void * arg);
int newfd;//定义一个全局整形的套接字
int main(int argc, char *argv[])
{
system("clear");
//message msg_accept;
int ret;
printf("服务器正在初始化......\n");
sleep(2);
int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == socket_fd)
{
perror("建立通信失败");
exit(1);
}
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORTNUMBER);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
printf("初始化服务器成功......\n");
printf("正在启动服务器......\n");
sleep(2);
if (-1 == bind(socket_fd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr)))
{
perror("绑定地址失败");
exit(2);
}
if(-1 == listen(socket_fd, MAXNUM))//最大监听用户人数为10
{
perror("监听失败");
exit(3);
}
printf("服务器启动成功......\n");
sqlite3 *db;
ret = sqlite3_open("./server.db", &db);//打开数据库
if(ret != SQLITE_OK)
{
printf("打开数据库失败\n");
}
printf("打开数据库成功......\n");
printf("正在等待客户端的连接......\n");
ret = sqlite3_close(db);
if(ret != SQLITE_OK)
{
printf("关闭数据库失败\n");
}
//创建一个单链表
list = createlinkedlist();
pthread_t pid;
while(1)
{
struct sockaddr_in client_addr;
int length = sizeof(struct sockaddr);
newfd = accept(socket_fd, (struct sockaddr *)(&client_addr), &length);
if (-1 == newfd)
{
perror("接收失败");
exit(1);
}
printf("客服端%d连上了服务器......\n",newfd);
pthread_create(&pid,NULL,(void*)func,(void*)newfd);
}
//close(newfd);
return 0;
}
void *func(void * arg)
{
int newfd = (int)arg;//强转为套接字类型
char sendbuff[1024] = {0};//服务器发送信息
char buff[1024] = {0};//把套接字先缓存到的区域
int ret;
static int num = 1000;//用作ID
// message *msg_accept = (message *)arg ;//把arg强转为结构体
while(1)
{
ret = read(newfd, buff,1024);
if(-1 == ret)
{
perror("读取错误");
exit(1);
}
memset(&msg_accept,0,sizeof(msg_accept));//清空结构体
memcpy(&msg_accept,buff,sizeof(msg_accept));//把收到的信息转换为结构体
//printf("msg_accept.name = %s\t,msg_accept.password = %s\n",msg_accept.name,msg_accept.password);
//printf("msg_accept.case_num = %d\n",msg_accept.case_num);
switch(msg_accept.case_num)
{
case 1 : //客户请求注册
{
printf("---------------------------------------------\n");
printf("客户端需要注册的名字为: %s 密码 :%s\n",msg_accept.name,msg_accept.password);
printf("---------------------------------------------\n");
sqlite3 *db;
char *errmsg;
ret = sqlite3_open("server.db",&db);
if(ret != SQLITE_OK)
{
perror("打开数据库失败");
exit(2);
}
char sql_insert[1024] = {0};
sprintf(sql_insert,"insert into server(id ,name,password) values(%d,'%s','%s');",num,msg_accept.name,msg_accept.password);
printf("----------------------以下信息已进入数据库-----------------------\n");
printf("%s\n",sql_insert);
printf("-----------------------------------------------------------------\n");
ret = sqlite3_exec(db,sql_insert,NULL,NULL,&errmsg);
if(ret != SQLITE_OK)
{
perror("插入数据库失败");
exit(3);
}
ret = sqlite3_close(db);
if(ret != SQLITE_OK)
{
perror("关闭数据库失败");
exit(4);
}
msg_send.case_snum = 0;
msg_send.id__s = num;
num++;
memset(sendbuff,0,1024);
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd ,sendbuff, 1024);
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
break;
}
case 2: //客户请求登录
{
printf("---------------------------------------------\n");
printf("有客户需要登录, 登录ID:%d 密码:%s \n",msg_accept.id,msg_accept.password);
printf("---------------------------------------------\n");
sqlite3 *db;
char *errmsg;
int row;
int column;
char**result;
ret = sqlite3_open("server.db",&db);
if(ret != SQLITE_OK)
{
perror("打开数据库失败");
exit(2);
}
char sql_client[1024] = {0};
sprintf(sql_client,"select id,password from server where id = %d and password = '%s';",msg_accept.id,msg_accept.password);
ret = sqlite3_get_table(db, sql_client, &result, &row, &column, &errmsg);
if(ret != SQLITE_OK)
{
perror("查询数据库失败");
exit(3);
}
int i;
int j;
printf("-------查询结果如下--------\n");
for(i = 1;i <= row;i++)
{
for(j = 0;j < column;j++)
{
printf("%s|",result[i * column + j]);
}
printf("\n");
}
printf("---------------------------\n");
ret = sqlite3_close(db);
if(ret != SQLITE_OK)
{
perror("关闭数据库失败");
exit(4);
}
if(column == 0)
{
printf("你登录的信息有误,请重新登录.\n");
msg_send.case_snum = 1;
memset(sendbuff,0,1024);
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd ,sendbuff, 1024);
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
break;
}
else//登录成功
{
printf("恭喜你登录成功.\n");
if(msg_accept.id == 1000)//管理员登录
{
memset(sendbuff,0,1024);
printf("管理员上线.\n");
msg_send.case_snum = 3;//管理登录成功后发送到客户端的指令
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd ,sendbuff, 1024);
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
}
else //普通用户登录成功
{
memset(sendbuff,0,1024);
printf("普通用户上线.\n");
msg_send.case_snum = 2;//普通用户登录成功后发送到客户端的指令
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd ,sendbuff, 1024);
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
}
//插入信息到链表
list = insert2(list, msg_accept.id, newfd);
printf("现在在线人物信息 :\n");
printf_list(list);
printf("在线人数为:%d\n", getcount(list));
while(1)
{
memset(buff,0,1024);
ret = read(newfd,buff,1024);
if(-1 == ret)
{
perror("读取失败");
exit(1);
}
memcpy(&msg_accept,buff,sizeof(msg_accept));
switch(msg_accept.case_numnext)
{
case 1://查看当前人数
{
/*
char str[1024] = {0};
sprintf(str,"当前在线人数为: %d\n",count);
ret = write(newfd,str,1024);
if(-1 == ret)
{
perror("写入人数失败");
exit(2);
}
*/
int count = getcount(list);//用链表查看当前的人数
memset(sendbuff ,0 ,1024);
msg_send.id__s = count;//用作id_s临时记录下在线的人数
printf("count = %d\n",msg_send.id__s);
msg_send.case_snum = 6;//查询在线人数
//memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd ,sendbuff, 1024);
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
sleep(1);
linkedlist *h = list;
int temp = 0;
while(h != NULL)
{
msg_send.num_s[temp] = h -> id_l;
temp++;
h = h -> next;
}
msg_send.i_s = temp;
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd ,sendbuff, 1024);
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
break;
}
case 2: //发送私聊
{
int send_newfd = queryfd(list, msg_accept.id);//查询私聊人物的FLAG
//是否有此人
// printf("查到的客户端是: %d\n", send_newfd);
int id_client = queryid(list,newfd);//查询发送消息人物的ID
//printf("id_client = %d\n",id_client);//打印他的ID
if(send_newfd != 0)//有此人
{
printf("客户端%d 私聊客户端%d 消息为 : %s\n",newfd,send_newfd,msg_accept.name);
memset(sendbuff ,0 ,1024);
msg_send.id__s = send_newfd;//用作id_s临时记录下客户端的FLAG
msg_send.case_snum = 4;//查询有这个ID
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd ,sendbuff, 1024);
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
memset(sendbuff,0,1024);
strcpy(msg_send.name_s,msg_accept.name);
msg_send.case_snum = 7;//用于发送私聊消息的指令
msg_send.id__s = id_client;//用于记录发送人的ID
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(send_newfd,sendbuff,1024);//发送给要私聊的人
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
memset(sendbuff,0,1024);
msg_send.case_snum = 8;//用于发聩消息发送成功了指令
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd,sendbuff,1024);//发送给发起私聊的人
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
}
else
{
printf("没有这个ID\n");
memset(sendbuff ,0 ,1024);
msg_send.case_snum = 5;//没有这个ID
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd ,sendbuff, 1024);
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
}
break;
}
case 3: //发送群聊
{
int id_client = queryid(list,newfd);//查询发送群聊消息人物的ID
printf("客户端%d发起了群聊,内容是:%s\n",newfd,msg_accept.name);
int i;
linkedlist *h = list;
//把在线人数都遍历出来
for(i = 0; i < getcount(list); i++)
{
if(h -> fd_l != newfd)
{
memset(sendbuff, 0, 1024);
strcpy(msg_send.name_s,msg_accept.name);//复制群聊的消息到服务器的结构体里面
msg_send.case_snum = 9;//用于发送群聊消息的指令
msg_send.id__s = id_client;//用于记录发送人的ID
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(h -> fd_l, sendbuff, 1024);
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
}
h = h -> next;
}
memset(sendbuff,0,1024);
msg_send.case_snum = 10;//用于发聩消息发送成功了指令
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd,sendbuff,1024);//发送给发起群聊的人
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
break;
}
case 4: //客户请求发送文件
{
int ret;
int accept_newfd = queryfd(list, msg_accept.id);//查询文件要发送到人物的FLAG
int id_send = queryid(list,newfd);//查询发送文件的ID
printf("客户端%d请求发送文件给客户端%d,文件名是: %s\n",newfd,accept_newfd,msg_accept.name);
memset(sendbuff,0,1024);
//先把名字发给要接受文件的人
msg_send.case_snum = 18;
msg_send.id__s = id_send;
strcpy(msg_send.name_s,msg_accept.name);
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(accept_newfd,sendbuff,1024);
if(-1 == ret)
{
perror("写入失败\n");
exit(1);
}
//把内容发给要接受文件的人
while(1)
{
char buffer_file[1024];
memset(buffer_file, 0, 1024);//清空缓存
if(recv(newfd, buffer_file, 1024, 0) < 0)
{
perror("接收失败");
exit(1);
}
printf("内容是 :\n");
printf("%s\n",buffer_file);
if(send(accept_newfd, buffer_file, 1024, 0) < 0)
{
perror("发送失败");
exit(1);
}
if(0 == strncmp(buffer_file, "END", 3))
{
break;
}
}
//把发送成功的消息发聩给发送者
memset(sendbuff,1024,0);
msg_send.case_snum = 19;
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd,sendbuff,1024);
if(-1 == ret)
{
perror("写入失败\n");
exit(1);
}
break;
}
case 5: //客户请求下线
{
printf("客户端%d请求下线\n",newfd);
list = dellinkedlist(list, newfd);
printf_list(list);
memset(sendbuff,0,1024);
msg_send.case_snum = 11;//用于发聩消息发送成功了指令
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd,sendbuff,1024);//发送给发起请求下线的人
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
//break;
goto out;
}
case 6://禁言
{
printf("管理员请求禁言,禁言的ID是%d\n",msg_accept.id);
memset(sendbuff, 0, 1024);
int jinyan_newfd = queryfd(list,msg_accept.id);//查询被禁言人的客户端
msg_send.case_snum = 12;
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(jinyan_newfd,sendbuff,1024);//发送给被禁言的人
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
//禁言成功反馈给管理员
msg_send.case_snum = 13;
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd,sendbuff,1024);//发送给被禁言的人
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
break;
}
case 7://解禁
{
printf("管理员请求解禁,解禁的ID是%d\n",msg_accept.id);
memset(sendbuff, 0, 1024);
int jiejin_newfd = queryfd(list,msg_accept.id);//查询被禁言人的客户端
msg_send.case_snum = 14;
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(jiejin_newfd,sendbuff,1024);//发送给被禁言的人
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
//解禁成功反馈给管理员
msg_send.case_snum = 15;
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd,sendbuff,1024);//发送给管理员
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
break;
}
case 8://踢人下线
{
printf("管理员请求踢人,被踢人的ID是%d\n",msg_accept.id);
memset(sendbuff, 0, 1024);
int tiren_newfd = queryfd(list,msg_accept.id);//查询被踢人的客户端
msg_send.case_snum = 16;
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(tiren_newfd,sendbuff,1024);//发送给被踢的人
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
//踢人成功反馈给管理员
msg_send.case_snum = 17;
memset(sendbuff, 0, 1024);
memcpy(sendbuff,&msg_send,sizeof(msg_send));
ret = write(newfd,sendbuff,1024);//发送给管理员
if(-1 == ret)
{
perror("写入失败");
exit(2);
}
break;
}
}
}
break;
}
break;
}
case 3:
{
printf("客户端%d请求退出\n",newfd);
goto outroom;
}
}//switch
out:
printf("-----------\n");
}//while(1)
outroom:
close(newfd);
}
linkedlist *createlinkedlist()
{
linkedlist *h;
h = NULL;
return h;
}
linkedlist *dellinkedlist(linkedlist *list, int fd)
{
linkedlist *p = list -> next;
linkedlist *h = list;
if(list -> fd_l == fd)
{
free(h);
return list -> next;
}
else
{
while(p -> fd_l != fd)
{
p = p -> next;
h = h -> next;
}
h -> next = p -> next;
free(p);
return list;
}
}
linkedlist *insert2(linkedlist *list, int id, int fd)
{
linkedlist *head, *p;
head = list;
p = (linkedlist *)malloc(sizeof(linkedlist));
if(head == NULL)
{
head = p;
p -> next = NULL;
}
else
{
p -> next = head;
head = p;
}
p -> id_l = id;
p -> fd_l = fd;
return head;
}
int getcount(linkedlist *list)
{
linkedlist *h = list;
int count = 0;
while(h != NULL)
{
count++;
h = h -> next;
}
return count;
}
int queryid(linkedlist *list, int fd)
{
linkedlist *p, *h;
h = list;
while(h != NULL)
{
if(fd == h -> fd_l)
{
return h -> id_l;
}
h = h -> next;
}
}
int queryfd(linkedlist *list, int id)
{
linkedlist *h = list;
while(h != NULL)
{
if(id == h -> id_l)
{
return h -> fd_l;
}
h = h -> next;
}
return 0;
}
void printf_list(linkedlist *list)
{
linkedlist *h = list;
while(h != NULL)
{
printf("在线人物的ID为 :%d FLAG : %d\n", h ->id_l, h -> fd_l);
h = h -> next;
}
printf("\n");
}