/***************************************************************
File Name: server.h
Author: 浮生流年
Function List: main() 主函数
Created Time: 2017年12月12日 星期二 20时17分13秒
**************************************************************/
#ifndef _UDP_NET_SOCKET_
#define _UDP_NET_SOCKET_
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sqlite3.h>
#define PORT 8888
struct userinfo
{
int flag;//
char buf[100];//
char account[20];
char password[20];
char nickname[100];
char moto[256];
int likes;
char vip[20];
char qq_email[64];
char administrator[20];//管理员
char msg[1024];//存储对话消息
char to_nickname[20];
int online_number;
char online_nickname[100][20];//存储在线人员名单
char file_name[64];//文件名称
char file_content[4096];//文件内容
char shut_up[20];//禁言标志位
char tmp_name[20];
};
typedef struct userinfo Userinfo;
struct node
{
struct sockaddr_in client_addr;
char nickname[20];
struct node *next;
};
typedef struct node Node;
void forgot(sqlite3 *ppdb, Userinfo *recvbuf, Node **head, struct sockaddr_in *tmp_addr, int *sockfd);
#endif
#include <stdio.h>
#include "server.h"
void server_save_info(sqlite3 *ppdb, Userinfo *recvbuf, Userinfo *sendbuf)
{
int ret;
char auff[1024];
sprintf(auff, "insert into save_info values('%s', '%s', '%s', '%s', '%d', '%s', '%s', '%s', '%s')", recvbuf->account, recvbuf->password,
recvbuf->nickname, recvbuf->moto, recvbuf->likes, recvbuf->vip, recvbuf->qq_email, recvbuf->administrator, recvbuf->shut_up);
ret = sqlite3_exec(ppdb, auff, NULL, NULL, NULL);
if (ret != SQLITE_OK)
{
perror("sqlite3_exec");
strcpy(sendbuf->buf, "帐号已存在!");
}
else
{
strcpy(sendbuf->buf, "注册成功!");
}
}
void server_login(sqlite3 *ppdb, Userinfo *recvbuf, Userinfo *sendbuf, Node **head, struct sockaddr_in *tmp_addr)
{
bzero(sendbuf, sizeof(*sendbuf));
char **dbresult = NULL;
char *errmsg = NULL;//用来存储错误信息字符串
int nrow;//查询出多少记录(总行数)
int ncolumn;//查询出来的记录有多少字段,(总列数)
int ret, i;
char cuff[1024];
sprintf(cuff, "select account, password, nickname, moto, likes, vip , administrator from save_info where account = '%s' and password = '%s'", recvbuf->account, recvbuf->password);
ret = sqlite3_get_table(ppdb, cuff, &dbresult, &nrow, &ncolumn, &errmsg);//执行成功返回SQLITE_OK,否则返回其他值
if (ret != SQLITE_OK)
{
perror("sqlite3_get_table_server_login");
return;
}
if (1 == nrow)
{
Node *tmp = (*head)->next;
while (tmp != (*head))
{
if (!strcmp(tmp->nickname, dbresult[9]))
{
strcpy(sendbuf->buf, "该帐号已在其他地方登录!");
return;
}
tmp = tmp->next;
}
strcpy(sendbuf->buf, "登录成功!");
strcpy(sendbuf->nickname, dbresult[9]);
strcpy(sendbuf->moto, dbresult[10]);
sendbuf->likes = (*dbresult[11]) - 48;
strcpy(sendbuf->vip, dbresult[12]);
strcpy(sendbuf->administrator, dbresult[13]);
Node *p = (Node *)malloc(sizeof(Node));//链表用来记录帐号是否已登录,登录的帐号接入链表
if (NULL == p)
{
printf("Malloc Failure !\n");
return;
}
p->client_addr.sin_family = tmp_addr->sin_family;
p->client_addr.sin_port = tmp_addr->sin_port;
p->client_addr.sin_addr.s_addr = tmp_addr->sin_addr.s_addr;
strcpy(p->nickname, dbresult[9]);
p->next = (*head)->next;
(*head)->next = p;//循环链表; 记忆:head始终在最有边,新来的结点在最左边,head->next 始终指向p
}
else
{
strcpy(sendbuf->buf, "帐号或密码错误");
}
}
void forgot_password(sqlite3 *ppdb, Userinfo *recvbuf, Node **head, struct sockaddr_in *tmp_addr, int *sockfd)
{
Userinfo sendbuf = {0};
bzero(&sendbuf, sizeof(sendbuf));
char **dbresult = NULL;
char *errmsg = NULL;//用来存储错误信息字符串
int nrow;//查询出多少记录(总行数)
int ncolumn;//查询出来的记录有多少字段,(总列数)
int ret, i;
char cuff[1024];
sprintf(cuff, "select account, password from save_info where qq_email = '%s'", recvbuf->qq_email);
ret = sqlite3_get_table(ppdb, cuff, &dbresult, &nrow, &ncolumn, &errmsg);//执行成功返回SQLITE_OK,否则返回其他值
if (ret != SQLITE_OK)
{
perror("sqlite3_get_table_server_login");
return;
}
if (1 == nrow)
{
strcpy(sendbuf.buf, "忘记密码");
strcpy(sendbuf.account, dbresult[2]);
strcpy(sendbuf.password, dbresult[3]);
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)tmp_addr, sizeof(*tmp_addr));
if (ret < 0)
{
perror("sendto_forgot_password");
return;
}
}
else
{
strcpy(sendbuf.buf, "该帐号未注册");
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)tmp_addr, sizeof(*tmp_addr));
if (ret < 0)
{
perror("sendto_forgot_password");
return;
}
}
}
void transmit_to(sqlite3 *ppdb, Userinfo *sendbuf, Userinfo *recvbuf)//存储接收方用户信息to_nickname
{
char **dbresult = NULL;
char *errmsg = NULL;//用来存储错误信息字符串
int nrow;//查询出多少记录(总行数)
int ncolumn;//查询出来的记录有多少字段,(总列数)
int ret, i;
char cuff[1024];
sprintf(cuff, "select shut_up, password, nickname, moto, likes, vip , administrator from save_info where nickname = '%s'", recvbuf->to_nickname);
ret = sqlite3_get_table(ppdb, cuff, &dbresult, &nrow, &ncolumn, &errmsg);//执行成功返回SQLITE_OK,否则返回其他值
if (ret != SQLITE_OK)
{
perror("sqlite3_get_table_server_login");
return;
}
if (1 == nrow)
{
strcpy(sendbuf->shut_up, dbresult[7]);
strcpy(sendbuf->nickname, dbresult[9]);//
strcpy(sendbuf->moto, dbresult[10]);
sendbuf->likes = (*dbresult[11]) - 48;
strcpy(sendbuf->vip, dbresult[12]);
strcpy(sendbuf->administrator, dbresult[13]);
}
}
void transmit(sqlite3 *ppdb, Userinfo *sendbuf, Userinfo *recvbuf)//存储发送方用户信息
{
char **dbresult = NULL;
char *errmsg = NULL;//用来存储错误信息字符串
int nrow;//查询出多少记录(总行数)
int ncolumn;//查询出来的记录有多少字段,(总列数)
int ret, i;
char cuff[1024];
sprintf(cuff, "select shut_up, password, nickname, moto, likes, vip , administrator from save_info where nickname = '%s'", recvbuf->nickname);
ret = sqlite3_get_table(ppdb, cuff, &dbresult, &nrow, &ncolumn, &errmsg);//执行成功返回SQLITE_OK,否则返回其他值
if (ret != SQLITE_OK)
{
perror("sqlite3_get_table_server_login");
return;
}
if (1 == nrow)
{
strcpy(sendbuf->shut_up, dbresult[7]);
strcpy(sendbuf->nickname, dbresult[9]);//
strcpy(sendbuf->moto, dbresult[10]);
sendbuf->likes = (*dbresult[11]) - 48;
strcpy(sendbuf->vip, dbresult[12]);
strcpy(sendbuf->administrator, dbresult[13]);
}
}
void transmit_back(sqlite3 *ppdb, Userinfo *recvbuf, struct sockaddr_in *tmp_addr, int *sockfd)
//存储发送方用户信息并直接返回发送方,用于处理客户端误操作或重复操作
{
Userinfo sendbuf = {0};
bzero(&sendbuf, sizeof(sendbuf));
char **dbresult = NULL;
char *errmsg = NULL;//用来存储错误信息字符串
int nrow;//查询出多少记录(总行数)
int ncolumn;//查询出来的记录有多少字段,(总列数)
int ret, i;
char cuff[1024];
sprintf(cuff, "select shut_up, password, nickname, moto, likes, vip , administrator from save_info where nickname = '%s'", recvbuf->nickname);
ret = sqlite3_get_table(ppdb, cuff, &dbresult, &nrow, &ncolumn, &errmsg);//执行成功返回SQLITE_OK,否则返回其他值
if (ret != SQLITE_OK)
{
perror("sqlite3_get_table_server_login");
return;
}
if (1 == nrow)
{
strcpy(sendbuf.shut_up, dbresult[7]);
strcpy(sendbuf.nickname, dbresult[9]);//
strcpy(sendbuf.moto, dbresult[10]);
sendbuf.likes = (*dbresult[11]) - 48;
strcpy(sendbuf.vip, dbresult[12]);
strcpy(sendbuf.administrator, dbresult[13]);
}
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)tmp_addr, sizeof(*tmp_addr));
if (ret < 0)
{
perror("sendto_transmit_back");
return;
}
}
void private_chat(sqlite3 *ppdb, Userinfo *recvbuf, Node **head, struct sockaddr_in *tmp_addr, int *sockfd)
{
int ret;
Userinfo sendbuf;
bzero(&sendbuf, sizeof(sendbuf));
Node *tmp = (*head)->next;
Node *p = (*head)->next;
while (p != *head)
{
p = p->next;
}
while (tmp != *head)
{
if (strcmp(tmp->nickname, recvbuf->to_nickname) == 0)//判断接收消息的用户是否已登录
{
strcpy(sendbuf.nickname, tmp->nickname);//把对方的名字发过去方便用于保存聊天记录
strcpy(sendbuf.msg, recvbuf->msg);
strcpy(sendbuf.tmp_name, recvbuf->nickname);
strcpy(sendbuf.buf, "1私聊");//发送给指定用户
transmit_to(ppdb, &sendbuf, recvbuf);//*********************************************************************
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)&tmp->client_addr, sizeof(tmp->client_addr));
if (ret < 0)
{
perror("sendto_private_char_to_nickname");
return;
}
bzero(&sendbuf, sizeof(sendbuf));
strcpy(sendbuf.buf, "2正在转发私聊信息");
transmit(ppdb, &sendbuf, recvbuf);//******************************************************************
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)tmp_addr, sizeof(*tmp_addr));//发送给自己告知已发送消息
bzero(&sendbuf, sizeof(sendbuf));
if (ret < 0)
{
perror("sendto_private_char_nickname_success");
return;
}
return;
}
tmp = tmp->next;
}
strcpy(sendbuf.buf, "3对方暂未登录");
transmit(ppdb, &sendbuf, recvbuf);//*********************************************************************
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)tmp_addr, sizeof(*tmp_addr));
bzero(&sendbuf, sizeof(sendbuf));//ke yi bu yao
if (ret < 0)
{
perror("sendto_private_char_nickname_not_login");
return;
}
}
void group_chat(sqlite3 *ppdb, Userinfo *recvbuf, Node **head, struct sockaddr_in *tmp_addr, int *sockfd)//群聊
{
int ret, flag = 0;
Userinfo sendbuf = {0};
bzero(&sendbuf, sizeof(sendbuf));
Node *tmp = (*head)->next;
while (tmp != *head)
{
if (tmp->client_addr.sin_port != tmp_addr->sin_port)
{
flag = 1;
strcpy(sendbuf.tmp_name, recvbuf->nickname);
strcpy(sendbuf.msg, recvbuf->msg);
strcpy(sendbuf.buf, "5发起群聊");
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)&tmp->client_addr, sizeof(tmp->client_addr));
bzero(&sendbuf, sizeof(sendbuf));
if (ret < 0)
{
perror("sendto_group_chat");
return;
}
}
tmp = tmp->next;
}
if (1 == flag)
{
strcpy(sendbuf.buf, "2群聊成功");
transmit(ppdb, &sendbuf, recvbuf);//*********************************************************************
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)tmp_addr, sizeof(*tmp_addr));
if (ret < 0)
{
perror("sendto_group_chat_success");
return;
}
}
else
{
strcpy(sendbuf.buf, "6群聊失败");
transmit(ppdb, &sendbuf, recvbuf);//*********************************************************************
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)tmp_addr, sizeof(*tmp_addr));
if (ret < 0)
{
perror("sendto_group_chat_faliure");
return;
}
}
}
void file_transfer(sqlite3 *ppdb, Userinfo *recvbuf, Node **head, struct sockaddr_in *tmp_addr, int *sockfd)//注意这个head传参
{
int ret, flag = 0;
Userinfo sendbuf = {0};
bzero(&sendbuf, sizeof(sendbuf));
Node *tmp = (*head)->next;
while (tmp != (*head))
{
if (!strcmp(tmp->nickname, recvbuf->to_nickname))
{
flag = 1;
strcpy(sendbuf.tmp_name, recvbuf->nickname);
strcpy(sendbuf.file_name, recvbuf->file_name);//拷贝文件名
strcpy(sendbuf.file_content, recvbuf->file_content);//拷贝文件内容
strcpy(sendbuf.buf, "7传输文件");
transmit_to(ppdb, &sendbuf, recvbuf);//*********************************************************************
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)&tmp->client_addr, sizeof(tmp->client_addr));
bzero(&sendbuf, sizeof(sendbuf));
if (ret < 0)
{
perror("sendto_group_chat");
return;
}
}
tmp = tmp->next;
}
if (1 == flag)
{
strcpy(sendbuf.buf, "2文件传输成功");
transmit(ppdb, &sendbuf, recvbuf);//*********************************************************************
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)tmp_addr, sizeof(*tmp_addr));
if (ret < 0)
{
perror("sendto_file_transfer_success");
return;
}
}
else
{
strcpy(sendbuf.buf, "6文件传输失败");
transmit(ppdb, &sendbuf, recvbuf);//*********************************************************************
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)tmp_addr, sizeof(*tmp_addr));
if (ret < 0)
{
perror("sendto_file_transfer_faliure");
return;
}
}
}
void online_number(sqlite3 *ppdb, Userinfo *sendbuf, Userinfo *recvbuf, Node **head)//查看在线人数以及打印名单
{
bzero(&sendbuf->online_nickname, sizeof(sendbuf->online_nickname));
sendbuf->online_number = 0;
Node *tmp = (*head)->next;
printf("****************&&&&&&&&&&&&&&&&&&1\n");
while (tmp != *head)
{
printf("****************&&&&&&&&&&&&&&&&&&&2\n");
// strcpy(sendbuf->online_nickname[sendbuf->online_number], tmp->nickname);//指针并没有malloc,等我有空malloc一下试试
// sendbuf->online_nickname[sendbuf->online_number] = tmp->nickname;
// sendbuf->online_nickname[sendbuf->online_number] = tmp->nickname;//这样的话只能传送地址,地址中的信息传递不了
strcpy(sendbuf->online_nickname[sendbuf->online_number], tmp->nickname);//数组越界:之前定义数组char online_nickname[100][100]?
printf("***********************&&&&&&&&&&3\n");
printf("tmp->nickname:%s\n", tmp->nickname);
printf("online_nickname:%s\n", sendbuf->online_nickname[sendbuf->online_number]);
sendbuf->online_number++;
tmp = tmp->next;
}
strcpy(sendbuf->buf, "4在线人数");
transmit(ppdb, sendbuf, recvbuf);//*********************************************************************
}
void give_like(sqlite3 *ppdb, Userinfo *recvbuf, Node **head, struct sockaddr_in *tmp_addr, int *sockfd)
{
int ret, i;
int nrow;
int ncolumn;
char cuff[1024];
char *errmsg = NULL;
char **dbresult = NULL;
Userinfo sendbuf = {0};
bzero(&sendbuf, sizeof(sendbuf));//应该多余吧
sprintf(cuff, "select likes from save_info where nickname = '%s'", recvbuf->to_nickname);
ret = sqlite3_get_table(ppdb, cuff, &dbresult, &nrow, &ncolumn, &errmsg);
if (ret != SQLITE_OK)
{
printf("select failure : %d(%s)\n", ret, errmsg);
return;
}
if (1 == nrow)//只要此用户注册过,就为其点赞
{
sprintf(cuff, "update save_info set likes = likes + %d where nickname = '%s'", 1, recvbuf->to_nickname);
ret = sqlite3_exec(ppdb, cuff, NULL, NULL, &errmsg);
if (ret != SQLITE_OK)
{
printf("update failure : %d(%s)\n", ret, errmsg);
return;
}
Node *tmp = (*head)->next;
while (tmp != (*head))//遍历登录用户
{
printf("$$$$$$$$$$##########$$$$$$$$$$$2\n");
if (!strcmp(tmp->nickname, recvbuf->to_nickname))//若登录,则向其发送提醒消息
{
printf("$$$$$$$$$$$$$$$$$#################$$$$$$$$$$$$$3\n");
strcpy(sendbuf.buf, "8已为该登录用户点赞");
transmit_to(ppdb, &sendbuf, recvbuf);//*********************************************************************
sendbuf.likes = *(dbresult[1]);
strcpy(sendbuf.tmp_name, recvbuf->nickname);
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)&tmp->client_addr, sizeof(tmp->client_addr));
bzero(&sendbuf, sizeof(sendbuf));
if (ret < 0)
{
perror("sendto_give_like");
return;
}
break;
}
tmp = tmp->next;
}
strcpy(sendbuf.buf, "9点赞成功");
transmit(ppdb, &sendbuf, recvbuf);//*********************************************************************
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)tmp_addr, sizeof(*tmp_addr));
if (ret < 0)
{
perror("sendto_give_like_success");
return;
}
}
else
{
strcpy(sendbuf.buf, "10点赞失败");
transmit(ppdb, &sendbuf, recvbuf);//*********************************************************************
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)tmp_addr, sizeof(*tmp_addr));
if (ret < 0)
{
perror("sendto_give_like_failure");
return;
}
}
}
void change_character_signature(sqlite3 *ppdb, Userinfo *recvbuf, struct sockaddr_in *tmp_addr, int *sockfd)//修改个性签名
{
int ret;
char moto[1024];
char *errmsg = NULL;
Userinfo sendbuf = {0};
sprintf(moto, "update save_info set moto = '%s' where nickname = '%s'", recvbuf->moto, recvbuf->nickname);
ret = sqlite3_exec(ppdb, moto, NULL, NULL, &errmsg);
if (ret != SQLITE_OK)
{
printf("update failure : %d(%s)\n", ret, errmsg);
return;
}
strcpy(sendbuf.moto, recvbuf->moto);
strcpy(sendbuf.buf, "11个性签名修改成功");
transmit(ppdb, &sendbuf, recvbuf);//*********************************************************************
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)tmp_addr, sizeof(*tmp_addr));
if (ret < 0)
{
perror("sendto_change_character_signature_");
return;
}
}
void register_member(sqlite3 *ppdb, Userinfo *recvbuf, struct sockaddr_in *tmp_addr, int *sockfd)//处理注册会员
{
int ret;
char member[1024];
char *errmsg = NULL;
Userinfo sendbuf = {0};
sprintf(member, "update save_info set vip = '%s' where nickname = '%s'", recvbuf->vip, recvbuf->nickname);
ret = sqlite3_exec(ppdb, member, NULL, NULL, &errmsg);
if (ret < 0)
{
perror("sqlite3_exec_register_member");
return;
}
transmit(ppdb, &sendbuf, recvbuf);//*********************************************************************
strcpy(sendbuf.vip, "荣耀会员");
strcpy(sendbuf.buf, "12注册会员成功");
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)tmp_addr, sizeof(*tmp_addr));
if (ret < 0)
{
perror("sendto_register_member");
return;
}
}
void shut_up_person(sqlite3 *ppdb, Userinfo *recvbuf, Node **head, struct sockaddr_in *tmp_addr, int *sockfd)//指定用户禁言(只针对群聊)
{
int ret, i;
int nrow;
int ncolumn;
char cuff[1024];
char *errmsg = NULL;
char **dbresult = NULL;
Userinfo sendbuf = {0};
bzero(&sendbuf, sizeof(sendbuf));//应该多余吧
sprintf(cuff, "select shut_up from save_info where nickname = '%s'", recvbuf->to_nickname);
ret = sqlite3_get_table(ppdb, cuff, &dbresult, &nrow, &ncolumn, &errmsg);
if (ret != SQLITE_OK)
{
printf("select failure : %d(%s)\n", ret, errmsg);
return;
}
if (1 == nrow)//只要此用户注册过,就可以禁言
{
sprintf(cuff, "update save_info set shut_up = '%s' where nickname = '%s'", recvbuf->shut_up, recvbuf->to_nickname);
ret = sqlite3_exec(ppdb, cuff, NULL, NULL, &errmsg);
if (ret != SQLITE_OK)
{
printf("update failure : %d(%s)\n", ret, errmsg);
return;
}
Node *tmp = (*head)->next;
while (tmp != (*head))//遍历登录用户
{
printf("$$$$$$$$$$##########$$$$$$$$$$$2\n");
if (!strcmp(tmp->nickname, recvbuf->to_nickname))//若登录,则向其发送提醒消息
{
printf("$$$$$$$$$$$$$$$$$#################$$$$$$$$$$$$$3\n");
strcpy(sendbuf.buf, "13已将该登录用户禁言");
transmit_to(ppdb, &sendbuf, recvbuf);//*********************************************************************
strcpy(sendbuf.tmp_name, recvbuf->nickname);
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)&tmp->client_addr, sizeof(tmp->client_addr));
bzero(&sendbuf, sizeof(sendbuf));
if (ret < 0)
{
perror("sendto_shut_up");
return;
}
break;
}
tmp = tmp->next;
}
strcpy(sendbuf.buf, "14禁言成功");
transmit(ppdb, &sendbuf, recvbuf);//*********************************************************************
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)tmp_addr, sizeof(*tmp_addr));
if (ret < 0)
{
perror("sendto_shut_up__success");
return;
}
}
else
{
strcpy(sendbuf.buf, "15禁言失败");
transmit(ppdb, &sendbuf, recvbuf);//*********************************************************************
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)tmp_addr, sizeof(*tmp_addr));
if (ret < 0)
{
perror("sendto_shut_up_failure");
return;
}
}
}
void shut_up_all(sqlite3 *ppdb, Userinfo *recvbuf, Node **head, struct sockaddr_in *tmp_addr, int *sockfd)//全员禁言(只针对群聊)
//新注册用户还能群聊,真尴尬!!!
{
int ret, i, flag = 0;
char sql[1024];
Userinfo sendbuf = {0};
sprintf(sql, "update save_info set shut_up = '%s' where nickname != '%s'", recvbuf->shut_up, recvbuf->nickname);
ret = sqlite3_exec(ppdb, sql, NULL, NULL, NULL);
if (ret < 0)
{
perror("sqlite3_exec_shut_up_all");
return;
}
strcpy(sendbuf.buf, "16全员禁言成功");
transmit(ppdb, &sendbuf, recvbuf);//*********************************************************************
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)tmp_addr, sizeof(*tmp_addr));
if (ret < 0)
{
perror("sendto_shut_up_all_success");
return;
}
Node *tmp = (*head)->next;//如果用户在线, 就发消息通知
while (tmp != *head)
{
if (tmp->client_addr.sin_port != tmp_addr->sin_port)
{
flag = 1;
strcpy(sendbuf.tmp_name, recvbuf->nickname);
strcpy(sendbuf.buf, "17本群开始禁言");
transmit_to(ppdb, &sendbuf, recvbuf);//*********************************************************************
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)&tmp->client_addr, sizeof(tmp->client_addr));
bzero(&sendbuf, sizeof(sendbuf));
if (ret < 0)
{
perror("sendto_group_chat");
return;
}
}
tmp = tmp->next;
}
}
void remove_banned(sqlite3 *ppdb, Userinfo *recvbuf, Node **head, struct sockaddr_in *tmp_addr, int *sockfd)//指定用户解禁(只针对群聊)
{
int ret, i;
int nrow;
int ncolumn;
char cuff[1024];
char *errmsg = NULL;
char **dbresult = NULL;
Userinfo sendbuf = {0};
sprintf(cuff, "select shut_up from save_info where nickname = '%s'", recvbuf->to_nickname);
ret = sqlite3_get_table(ppdb, cuff, &dbresult, &nrow, &ncolumn, &errmsg);
if (ret != SQLITE_OK)
{
printf("select failure : %d(%s)\n", ret, errmsg);
return;
}
if (1 == nrow)//只要此用户注册过,就可以解禁
{
sprintf(cuff, "update save_info set shut_up = '%s' where nickname = '%s'", recvbuf->shut_up, recvbuf->to_nickname);
ret = sqlite3_exec(ppdb, cuff, NULL, NULL, &errmsg);
if (ret != SQLITE_OK)
{
printf("update failure : %d(%s)\n", ret, errmsg);
return;
}
Node *tmp = (*head)->next;
while (tmp != (*head))//遍历登录用户
{
printf("$$$$$$$$$$##########$$$$$$$$$$$2\n");
if (!strcmp(tmp->nickname, recvbuf->to_nickname))//若登录,则向其发送提醒消息
{
printf("$$$$$$$$$$$$$$$$$#################$$$$$$$$$$$$$3\n");
strcpy(sendbuf.buf, "18已将该登录用户禁言");
transmit_to(ppdb, &sendbuf, recvbuf);//*********************************************************************
strcpy(sendbuf.tmp_name, recvbuf->nickname);
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)&tmp->client_addr, sizeof(tmp->client_addr));
bzero(&sendbuf, sizeof(sendbuf));
if (ret < 0)
{
perror("sendto_remove_banned");
return;
}
break;
}
tmp = tmp->next;
}
strcpy(sendbuf.buf, "19解禁成功");
transmit(ppdb, &sendbuf, recvbuf);//*********************************************************************
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)tmp_addr, sizeof(*tmp_addr));
if (ret < 0)
{
perror("sendto_shut_up__success");
return;
}
}
else
{
strcpy(sendbuf.buf, "20解禁失败");
transmit(ppdb, &sendbuf, recvbuf);//*********************************************************************
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)tmp_addr, sizeof(*tmp_addr));
if (ret < 0)
{
perror("sendto_shut_up_failure");
return;
}
}
}
void remove_banned_all(sqlite3 *ppdb, Userinfo *recvbuf, Node **head, struct sockaddr_in *tmp_addr, int *sockfd)//全员解禁(只针对群聊)
{
int ret, i, flag = 0;
char sql[1024];
Userinfo sendbuf = {0};
sprintf(sql, "update save_info set shut_up = '%s' where nickname != '%s'", recvbuf->shut_up, recvbuf->nickname);
ret = sqlite3_exec(ppdb, sql, NULL, NULL, NULL);
if (ret < 0)
{
perror("sqlite3_exec_shut_up_all");
return;
}
strcpy(sendbuf.buf, "21全员解禁成功");
transmit(ppdb, &sendbuf, recvbuf);//*********************************************************************
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)tmp_addr, sizeof(*tmp_addr));
if (ret < 0)
{
perror("sendto_shut_up_all_success");
return;
}
Node *tmp = (*head)->next;//如果用户在线, 就发消息通知
while (tmp != *head)
{
if (tmp->client_addr.sin_port != tmp_addr->sin_port)
{
flag = 1;
strcpy(sendbuf.tmp_name, recvbuf->nickname);
strcpy(sendbuf.buf, "22本群已被解禁");
transmit_to(ppdb, &sendbuf, recvbuf);//*********************************************************************
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)&tmp->client_addr, sizeof(tmp->client_addr));
bzero(&sendbuf, sizeof(sendbuf));
if (ret < 0)
{
perror("sendto_group_chat");
return;
}
}
tmp = tmp->next;
}
}
void kicking(sqlite3 *ppdb, Userinfo *recvbuf, Node **head, struct sockaddr_in *tmp_addr, int *sockfd)//踢人(强制下线)
{
int ret, i;
int nrow;
int ncolumn;
char cuff[1024];
char *errmsg = NULL;
char **dbresult = NULL;
Userinfo sendbuf = {0};
Userinfo RecvBuf = {0};
sprintf(cuff, "select shut_up from save_info where nickname = '%s'", recvbuf->to_nickname);//
ret = sqlite3_get_table(ppdb, cuff, &dbresult, &nrow, &ncolumn, &errmsg);
if (ret != SQLITE_OK)
{
printf("select failure : %d(%s)\n", ret, errmsg);
return;
}
if (1 == nrow)//注册过(判断此用户是否注册过)
{
Node *tmp = *head;
while (tmp->next != *head)//判断该用户是否已登录
{
if (!strcmp(tmp->next->nickname, recvbuf->to_nickname))//若登录,则向其发送提醒消息
{
strcpy(sendbuf.buf, "23已将该登录用户强制下线");
transmit_to(ppdb, &sendbuf, recvbuf);//*********************************************************************
strcpy(sendbuf.tmp_name, recvbuf->nickname);
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)&tmp->next->client_addr, sizeof(tmp->next->client_addr));
Node *p = tmp->next;//释放节点必须要在发送数据后,否则节点地址及内容就消失了,无法传送到指定客户端
tmp->next = p->next;
free(p);
bzero(&sendbuf, sizeof(sendbuf));
if (ret < 0)
{
perror("sendto_remove_banned");
return;
}
strcpy(sendbuf.buf, "24踢人成功");
transmit(ppdb, &sendbuf, recvbuf);//*********************************************************************
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)tmp_addr, sizeof(*tmp_addr));
bzero(&sendbuf, sizeof(sendbuf));
if (ret < 0)
{
perror("sendto_shut_up__success");
return;
}
bzero(&sendbuf,sizeof(sendbuf));
Node *temp = (*head)->next;
while (temp != *head)
{
if (strcmp(temp->nickname, recvbuf->nickname))
{
strcpy(sendbuf.tmp_name, recvbuf->to_nickname);
strcpy(sendbuf.buf, "29好友下线通知");
strcpy(RecvBuf.nickname, temp->nickname);
transmit(ppdb, &sendbuf, &RecvBuf);//*********************************************************************
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)&temp->client_addr, sizeof(temp->client_addr));
bzero(&sendbuf, sizeof(sendbuf));
bzero(&RecvBuf, sizeof(RecvBuf));
if (ret < 0)
{
perror("sendto_group_chat");
return;
}
}
temp = temp->next;
}
return;
}
tmp = tmp->next;
}
strcpy(sendbuf.buf, "25踢人失败");//注册但未登录
transmit(ppdb, &sendbuf, recvbuf);//*********************************************************************
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)tmp_addr, sizeof(*tmp_addr));
bzero(&sendbuf, sizeof(sendbuf));
if (ret < 0)
{
perror("sendto_shut_up__success");
return;
}
return;
}
else//没注册过
{
strcpy(sendbuf.buf, "26踢人失败");
transmit(ppdb, &sendbuf, recvbuf);//*********************************************************************
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)tmp_addr, sizeof(*tmp_addr));
if (ret < 0)
{
perror("sendto_shut_up_failure");
return;
}
}
}
void offline(sqlite3 *ppdb, Userinfo *recvbuf, Node **head, struct sockaddr_in *tmp_addr, int *sockfd)//主动下线(不终止客户端)
{
int ret;
Userinfo sendbuf = {0};
bzero(&sendbuf, sizeof(sendbuf));
Userinfo RecvBuf = {0};
Node *tmp = (*head)->next;
while (tmp != *head)
{
if (strcmp(tmp->nickname, recvbuf->nickname))
{
strcpy(sendbuf.tmp_name, recvbuf->nickname);
strcpy(sendbuf.buf, "29好友下线通知");
strcpy(RecvBuf.nickname, tmp->nickname);
transmit(ppdb, &sendbuf, &RecvBuf);//*********************************************************************
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)&tmp->client_addr, sizeof(tmp->client_addr));
bzero(&sendbuf, sizeof(sendbuf));
bzero(&RecvBuf, sizeof(RecvBuf));
if (ret < 0)
{
perror("sendto_group_chat");
return;
}
}
tmp = tmp->next;
}
Node *temp = *head;//这种方式较好
while (temp->next != *head)
{
if (!strcmp(temp->next->nickname, recvbuf->nickname))
{
Node *p = temp->next;
temp->next = p->next;
free(p);
break;
}
temp = temp->next;
}
strcpy(sendbuf.buf, "27下线成功");//
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)tmp_addr, sizeof(*tmp_addr));
if (ret < 0)
{
perror("sendto_offline");
return;
}
}
void terminate_client(sqlite3 *ppdb, Userinfo *recvbuf, Node **head, int *sockfd)//主动下线(终止客户端)
{
int ret;
Userinfo sendbuf = {0};
bzero(&sendbuf, sizeof(sendbuf));
Userinfo RecvBuf = {0};
Node *tmp = (*head)->next;
while (tmp != *head)
{
if (strcmp(tmp->nickname, recvbuf->nickname))
{
strcpy(sendbuf.tmp_name, recvbuf->nickname);
strcpy(sendbuf.buf, "29好友下线通知");
strcpy(RecvBuf.nickname, tmp->nickname);
transmit(ppdb, &sendbuf, &RecvBuf);//*********************************************************************
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)&tmp->client_addr, sizeof(tmp->client_addr));
bzero(&sendbuf, sizeof(sendbuf));
bzero(&RecvBuf, sizeof(RecvBuf));
if (ret < 0)
{
perror("sendto_group_chat");
return;
}
}
tmp = tmp->next;
}
Node *temp = *head;//这种方式较好
while (temp->next != *head)
{
if (!strcmp(temp->next->nickname, recvbuf->nickname))
{
Node *p = temp->next;
temp->next = p->next;
free(p);
break;
}
temp = temp->next;
}
}
void friends_online_notification(sqlite3* ppdb, Userinfo *recvbuf, Node **head, struct sockaddr_in *tmp_addr, int *sockfd)//好友上线通知
{
int ret;
Userinfo sendbuf = {0};
bzero(&sendbuf, sizeof(sendbuf));
Userinfo RecvBuf = {0};
Node *tmp = (*head)->next;
while (tmp != *head)
{
if (strcmp(tmp->nickname, recvbuf->nickname))//链表中所有人除了自己
{
strcpy(sendbuf.tmp_name, recvbuf->nickname);
strcpy(sendbuf.buf, "28好友上线通知");
strcpy(RecvBuf.nickname, tmp->nickname);
transmit(ppdb, &sendbuf, &RecvBuf);//*********************************************************************
ret = sendto(*sockfd, &sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)&tmp->client_addr, sizeof(tmp->client_addr));
bzero(&sendbuf, sizeof(sendbuf));
bzero(&RecvBuf, sizeof(RecvBuf));
if (ret < 0)
{
perror("sendto_group_chat");
return;
}
}
tmp = tmp->next;
}
}
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include "server.h"
#define PORT 8888
int main()
{
int sockfd, length, ret, position;
struct sockaddr_in server_addr;
// struct sockaddr_in client_addr[100] = {0};//一次性记忆客户端,通过find_addr函数寻找,服务器停止后释放client_addr[100]中保存的内容
struct sockaddr_in tmp_addr;
char admin[512];
Userinfo Sendbuf = {0};
Userinfo Recvbuf = {0};
// Userinfo recordbuf[100] = {0};
sqlite3 *ppdb = NULL;
char account[20] = "88888888";//初始化管理员信息
char password[20] = "88888888";
char nickname[100] = "浮生流年";
char moto[256] = "山上山,水中水";
int likes = 8888;
char vip[20] = "至尊会员";
char qq_email[64] = "1186461326";
char administrator[20] = "管理员";
char shut_up[20] = "未禁";
Node *head = (Node *)malloc(sizeof(Node));
if (NULL == head)
{
printf("Malloc Failure!\n");
return;
}
head->next = head;
ret = sqlite3_open("user.db", &ppdb);
if (ret != SQLITE_OK)
{
perror("sqlite3_open");
exit(1);
}
ret = sqlite3_exec(ppdb, "create table if not exists save_info(account text primary key, password text, nickname text, moto text, likes integer, vip text, qq_email text, administrator text, shut_up text);", NULL, NULL, NULL);
if (ret != SQLITE_OK)
{
perror("sqlite3_exec_create_table");
exit(1);
}
sprintf(admin, "insert into save_info values('%s', '%s', '%s', '%s', '%d', '%s', '%s', '%s', '%s')", account, password, nickname,
moto, likes, vip, qq_email, administrator, shut_up);//服务器启动后自行生成一个管理员帐号
ret = sqlite3_exec(ppdb, admin, NULL, NULL, NULL);
if (ret != SQLITE_OK)
{
perror("sqlite3_exec_insert into");
exit(1);
}
sockfd = socket(PF_INET, SOCK_DGRAM, 0);
if (-1 == sockfd)
{
perror("socket");
exit(1);
}
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = PORT;
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret < 0)
{
perror("bind");
exit(1);
}
while (1)//此程序默认所有登录用户都在一个群里,暂无加群功能
{
length = sizeof(tmp_addr);
ret = recvfrom(sockfd, &Recvbuf, sizeof(Recvbuf), 0, (struct sockaddr *)&tmp_addr, &length);
if (ret < 0)
{
perror("recvfrom");
exit(1);
}
switch (Recvbuf.flag)
{
case 1://注册
server_save_info(ppdb, &Recvbuf, &Sendbuf);
ret = sendto(sockfd, &Sendbuf, sizeof(Sendbuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
if (ret < 0)
{
perror("sendto_server_save_info");
break;
}
bzero(&Recvbuf, sizeof(Recvbuf));
bzero(&Sendbuf, sizeof(Sendbuf));
if (ret < 0)
{
perror("sendto_server_register");
exit(1);
}
break;
case 2://登录
server_login(ppdb, &Recvbuf, &Sendbuf, &head, &tmp_addr);
bzero(&Recvbuf, sizeof(Recvbuf));
ret = sendto(sockfd, &Sendbuf, sizeof(Sendbuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
if (ret < 0)
{
perror("sendto_server_login");
exit(1);
}
bzero(&Sendbuf, sizeof(Sendbuf));
break;
case 3 ://忘记密码
forgot_password(ppdb, &Recvbuf, &head, &tmp_addr, &sockfd);
break;
case 4://私聊
private_chat(ppdb, &Recvbuf, &head, &tmp_addr, &sockfd);
bzero(&Recvbuf, sizeof(Recvbuf));
break;
case 5://群聊
group_chat(ppdb, &Recvbuf, &head, &tmp_addr, &sockfd);
bzero(&Recvbuf, sizeof(Recvbuf));
break;
case 6://文件传输
file_transfer(ppdb, &Recvbuf, &head, &tmp_addr, &sockfd);
bzero(&Recvbuf, sizeof(Recvbuf));
break;
case 7://在线人数
bzero(&Sendbuf, sizeof(Sendbuf));
online_number(ppdb, &Sendbuf, &Recvbuf, &head);
// printf("%s\n", Sendbuf.online_nickname[0]);
ret = sendto(sockfd, &Sendbuf, sizeof(Sendbuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
if (ret < 0)
{
perror("sendto_onine_number");
break;
}
break;
case 8://查看聊天记录(融合了)
break;
case 9://快捷消息(融合了)
break;
case 10://点赞
give_like(ppdb, &Recvbuf, &head, &tmp_addr, &sockfd);
break;
case 11://修改签名
change_character_signature(ppdb, &Recvbuf, &tmp_addr, &sockfd);
break;
case 12://vip(充钱)
register_member(ppdb, &Recvbuf, &tmp_addr, &sockfd);
break;
case 13://指定用户禁言(管理员权限)(只针对群聊,不影响私聊)
shut_up_person(ppdb, &Recvbuf, &head, &tmp_addr, &sockfd);
break;
case 14://全员禁言(管理员权限)(注册过但没登录的也要禁言,确保用户上线后处于被动静默状态)(只针对群聊,不影响私聊)
shut_up_all(ppdb, &Recvbuf, &head, &tmp_addr, &sockfd);
break;
case 15://指定用户解禁 (管理员权限)(只针对群聊,不影响私聊)
remove_banned(ppdb, &Recvbuf, &head, &tmp_addr, &sockfd);
break;
case 16://全员解禁(管理员权限)(注册过但没登录的也要解禁,确保用户上线后处于言论自由状态)(只针对群聊,不影响私聊)
remove_banned_all(ppdb, &Recvbuf, &head, &tmp_addr, &sockfd);
break;
case 17://踢人(管理员权限)(不终止客户端程序运行)
kicking(ppdb, &Recvbuf, &head, &tmp_addr, &sockfd);
break;
case 18://退出(下线)不终止客户端
offline(ppdb, &Recvbuf, &head, &tmp_addr, &sockfd);
break;
case 19://退出(下线)终止客户端
terminate_client(ppdb, &Recvbuf, &head, &sockfd);
break;
case 20:transmit_back(ppdb, &Recvbuf, &tmp_addr, &sockfd);//处理客户端因误操作或重复操作而导致信息丢失
break;
case 21://好友上线通知
friends_online_notification(ppdb, &Recvbuf, &head, &tmp_addr, &sockfd);
break;
}
}
close(sockfd);
return 0;
}