基于Linux的多功能聊天室
作者:网络转载 发布时间:[ 2015/2/4 17:58:55 ] 推荐标签:Linux 操作系统
其实这个项目在我电脑已经躺了多时,初写完项目规划后,我认认真真地去实现了它,后来拿着这个项目区参加了面试,同样面试官也拿这个项目来问我,当然我是做过一遍了,而且为了面试,我将什么strcpy,strlen等常用的函数都自己实现了一遍,说着,我感觉自己有点挺用功的样子呢!
后来,工作也定下来了,等三方,然后继续帮助我的导师做项目,经过老师的威逼利诱下,我屈服了,又把智能家居系统作为项目,同时也是我的毕业设计,而且功能还要十分完善的说,好吧,别人的简单,但我也无所谓,因为看到技术二字,我必然是两眼放光的那种,特别喜欢那种突然我想到咋么解决了,然后帮功能实现了那种感觉,像是上瘾了一样,(果然是当程序员的料)
项目回想与思考
嗯,我的项目基本上的功能和项目规划里面基本上是一致的,而且功能也是非常完善了,基本上能够实现了我所需要的功能,但是我也要思考我在整个项目过程中的得失,我在项目的思考中,其实把他定义错了,因为是一个非常小的聊天室的功能,其实我无需使用数据库来作为登陆与否的查询方法,其实完全可以使用链表的方法来做客户端的登录,这样才是不会造成资源的浪费
项目代码
我将分两篇来讲述我的项目,第一篇(也是这篇为服务器篇);第二篇为客户端篇,当然里面的代码基本上全是我个人所写,也参考过一部分别的代码!
Makefile
基本上我也忘得差不多了,对这个项目,我感觉淡淡的陌生感,但是重拾还是非常容易的嘛!看一个项目咋么形成,Makefile不容错过!
main=insert.o chatroom.o sql.o passwd.o string.o cmd.o socket.o
chatroom:$(main)
@gcc$(main)-o chatroom-lsqlite3
passwd.o:passwd.c
@gcc passwd.c-c
insert.o:insert.c
@gcc insert.c-c
sql.o:sql.c
@gcc sql.c-c
string.o:string.c
@gcc string.c-c
cmd.o:cmd.c
@gcc cmd.c-c
socket.o:socket.c
@gcc socket.c-c
.PHONY:clean cleanall
clean:
@rm*.o
cleanall:
@rm*.o chatroom
通过这个我们不难发现这个项目调动了什么,和哪些文件!
passwd.c文件分析
先不说我们把代码贴出来先!
#include"data.h"
void reg_db(sqlite3*db,char**errmsg,char*name,char*passwd)//注册插入
{
char sql[1024];
int rc;
sprintf(sql,"insert into user(name,passwd)values('%s','%s')",name,passwd);
rc=sqlite3_exec(db,sql,NULL,NULL,errmsg);
is_sqlite(rc);
}
void log_db(sqlite3*db,char**errmsg,char*name,int sockfd)//登陆插入
{
char sql[1024];
int rc;
sprintf(sql,"insert into online(name,socket,flag)values('%s',%d,1)",name,sockfd);
rc=sqlite3_exec(db,sql,NULL,NULL,errmsg);
is_sqlite(rc);
}
void delete_online_db(sqlite3*db,char**errmsg,int sockfd)//删除登陆
{
char sql[1024];
int rc;
sprintf(sql,"delete from online where socket=%d",sockfd);
rc=sqlite3_exec(db,sql,NULL,NULL,errmsg);
is_sqlite(rc);
}
int read_user(sqlite3*db,char**errmsg,char*user)//询问有无此用户
{
int rc;
int i;
sqlite3_stmt*stmt=NULL;
rc=sqlite3_prepare(db,"select*from user",-1,&stmt,0);
is_sqlite_ok(rc);
rc=sqlite3_step(stmt);
int userflag=1;
while(rc==SQLITE_ROW)
{
userflag=my_strcmp(user,sqlite3_column_text(stmt,1));
if(userflag==0)
{
return USERIN;
}
rc=sqlite3_step(stmt);
}
return USEROUT;
}
int read_id(sqlite3*db,char**errmsg,char*user)//询问有无此用户
{
int rc;
int i;
sqlite3_stmt*stmt=NULL;
rc=sqlite3_prepare(db,"select*from user",-1,&stmt,0);
is_sqlite_ok(rc);
rc=sqlite3_step(stmt);
int userflag=1;
while(rc==SQLITE_ROW)
{
userflag=my_strcmp(user,sqlite3_column_text(stmt,1));
if(userflag==0)
{
return atoi(sqlite3_column_text(stmt,0));
}
rc=sqlite3_step(stmt);
}
return USEROUT;
}
void read_id_name(sqlite3*db,char**errmsg,vpChat temp)//询问有无此用户
{
int rc;
int i;
sqlite3_stmt*stmt=NULL;
rc=sqlite3_prepare(db,"select*from user",-1,&stmt,0);
is_sqlite_ok(rc);
rc=sqlite3_step(stmt);
int userflag=1;
while(rc==SQLITE_ROW)
{
userflag=my_atoi(sqlite3_column_text(stmt,0));
if(userflag==temp->flag)
{
my_strcpy(temp->name,sqlite3_column_text(stmt,1));
}
rc=sqlite3_step(stmt);
}
}
int read_pass(sqlite3*db,char**errmsg,char*user,char*passwd)//用于用户验证
{
int rc;
int i;
sqlite3_stmt*stmt=NULL;
rc=sqlite3_prepare(db,"select*from user",-1,&stmt,0);
is_sqlite_ok(rc);
rc=sqlite3_step(stmt);
int userflag=1;
int passwdflag=1;
while(rc==SQLITE_ROW)
{
userflag=my_strcmp(user,sqlite3_column_text(stmt,1));
passwdflag=my_strcmp(passwd,sqlite3_column_text(stmt,2));
if(userflag==0&&passwdflag==0)
{
return PASSWDOK;
}
rc=sqlite3_step(stmt);
}
return PASSWDNO;
}
int read_online_ok(sqlite3*db,char**errmsg,char*user)//用于验证在线用户
{
int rc;
int i;
sqlite3_stmt*stmt=NULL;
rc=sqlite3_prepare(db,"select*from online",-1,&stmt,0);
is_sqlite_ok(rc);
rc=sqlite3_step(stmt);
int userflag=1;
while(rc==SQLITE_ROW)
{
userflag=my_strcmp(user,sqlite3_column_text(stmt,1));
if(userflag==0)
{
return ONLINEIN;
}
rc=sqlite3_step(stmt);
}
return ONLINEOUT;
}
哦,这个原来是用来登录注册用的呀!
那么我在来看看passwd.h呢!
void reg_db(sqlite3*db,char**errmsg,char*name,char*passwd);
int read_user(sqlite3*db,char**errmsg,char*user);
int read_pass(sqlite3*db,char**errmsg,char*user,char*passwd);//用于用户验证
int read_online_ok(sqlite3*db,char**errmsg,char*user);
void delete_online_db(sqlite3*db,char**errmsg,int sockfd);
int read_id(sqlite3*db,char**errmsg,char*user);//询问有无此用户
void read_id_name(sqlite3*db,char**errmsg,vpChat temp);//询问有无此用户
原来是对函数进行申明啊!
但是#include”data.h”这个文件又是干什么的呢?
那么data.h按照猜测肯定是各类头文件的引用喽!
#ifndef__DATA__
#define__DATA__
#define MAXSIZE 100
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<netdb.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<ctype.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sqlite3.h>
#include<unistd.h>
#include<signal.h>
#include<time.h>
#include<termios.h>
#include<assert.h>
#define portnumber 8000//宏定义端口号
struct chat
{
char name[20];//用户名
char passwd[20];//密码
int cmd;//命令
int revert;//返回值
char toname[20];//目标客户名
char msg[800];//发送信息
int flag;
int sockfd;
char time[40];
char filename[40];
};
typedef struct chat stChat;
typedef struct chat*vpChat;
enum cmd
{
LOGID=0,
REG=1,
LOG=2,
USERHELP=3,
USEREXIT=4,
CHAT=3,
ALL=4,
SMILE=5,
WELCOME=6,
EXIT=7,
HELP=8,
PASSWD=9,
BOOT=10,
STEP=11,
BAN=12,
SET=13,
SEE=14,
DATA=15,
SEND=16,
CHANGE=17
};
enum revert
{
USERIN=1,
USEROUT=-1,
PASSWDOK=2,
PASSWDNO=-2,
ONLINEIN=3,
ONLINEOUT=-3,
REGNO=-4,
REGOK=4,
MYFLAGOK=-5,
MYFLAGNO=-6,
TOFLAGOK=-7,
TOFLAGNO=-8,
CHATOK=1,
ALLOK=6,
SMILEOK=6,
WELCOMEOK=6,
SEEOK=7,
BOOTOK=1,
DATAOK=8,
SENDOK=2
};
#endif
果然与我们的猜想差不多啊!
insert.c文件分析
#include"data.h"
void insert_server()//服务器运行提示
{
system("reset");
printf(" **********************************
");
printf(" *欢迎使用*
");
printf(" *聊天室服务器*
");
printf(" **********************************
");
}
sogo,这文件原来是给我们看服务器启动时的界面的呀!
sql.c文件分析
看这名字,肯定跟数据库有关!
#include"data.h"
void is_malloc_ok(vpChat*list)
{
*list=(vpChat)malloc(sizeof(stChat));
if(*list==NULL)
{
exit(1);
}
}
void is_sqlite(int rc)//测试数据库
{
if(rc==SQLITE_OK)
{
printf("sqlite%d succse
",__LINE__);
}
else
{
printf("数据库发生错误,请使用SQLITE3看数据库!
");
printf("sqlite%d error
",__LINE__);
exit(1);
}
}
void is_sqlite_ok(int rc)
{
if(rc==SQLITE_OK)
{
printf("sqlite%d succse
",__LINE__);
}
else
{
printf("sqlite%d error
",__LINE__);
}
}
void open_db(sqlite3**db)//打开数据库
{
int rc;
rc=sqlite3_open("server.db",db);
is_sqlite(rc);
}
void creat_user_db(sqlite3*db,char**errmsg)//建立user数据表
{
int rc;
rc=sqlite3_exec(db,"create table user(id integer primary key autoincrement,name text,passwd text)",NULL,NULL,errmsg);
is_sqlite_ok(rc);
}
void creat_data_db(sqlite3*db,char**errmsg)//建立data数据表
{
int rc;
rc=sqlite3_exec(db,"create table data(id integer primary key autoincrement,time text,name text,toname text,msg text)",NULL,NULL,errmsg);
is_sqlite_ok(rc);
}
void creat_online_db(sqlite3*db,char**errmsg)//建立online数据表
{
int rc;
rc=sqlite3_exec(db,"create table online(id integer primary key autoincrement,name text,socket integer,flag integer)",NULL,NULL,errmsg);
is_sqlite_ok(rc);
}
void creat_server_db(sqlite3*db,char**errmsg)//建立server数据表
{
int rc;
rc=sqlite3_exec(db,"create table server(id integer primary key autoincrement,time text)",NULL,NULL,errmsg);
is_sqlite_ok(rc);
}
void insert_server_db(sqlite3*db,char*time,char**errmsg)//向server数据库插入数据
{
int rc;
char sql[1024];
sprintf(sql,"insert into server(time)values('%s')",time);
rc=sqlite3_exec(db,sql,NULL,NULL,errmsg);
is_sqlite(rc);
printf("数据库已经录入完毕
");
}
void insert_data_db(sqlite3*db,char**errmsg,char*time,vpChat temp)//插入聊天记录
{
int rc;
char sql[1024];
sprintf(sql,"insert into data(time,name,toname,msg)values('%s','%s','%s','%s')",time,temp->name,temp->toname,temp->msg);
rc=sqlite3_exec(db,sql,NULL,NULL,errmsg);
is_sqlite(rc);
printf("聊天记录已经录入完毕
");
}
void delete_clean_db(sqlite3*db,char*tablename,char**errmsg)//清空数据库
{
char sql[1024];
int rc;
sprintf(sql,"delete from%s where name!='root'",tablename);
rc=sqlite3_exec(db,"delete from student",NULL,NULL,errmsg);
is_sqlite(rc);
}
void read_db_ok(sqlite3*db,char*errmsg,char*tablename)//用于检测数据库
{
int rc;
int i;
char sql[1024];
sqlite3_stmt*stmt=NULL;
sprintf(sql,"select*from%s",tablename);
rc=sqlite3_prepare(db,sql,-1,&stmt,0);
is_sqlite_ok(rc);
rc=sqlite3_step(stmt);
int ncolumn;
ncolumn=sqlite3_column_count(stmt);
while(rc==SQLITE_ROW)
{
for(i=0;i<ncolumn;i++)
{
printf("%s|",sqlite3_column_text(stmt,i));
}
printf("
");
rc=sqlite3_step(stmt);
}
}
int read_online_fd(sqlite3*db,char**errmsg,char*user)//获取FD
{
int rc;
int i;
char fd[100];
sqlite3_stmt*stmt=NULL;
rc=sqlite3_prepare(db,"select*from online",-1,&stmt,0);
is_sqlite_ok(rc);
rc=sqlite3_step(stmt);
int userflag=1;
while(rc==SQLITE_ROW)
{
userflag=my_strcmp(user,sqlite3_column_text(stmt,1));
if(userflag==0)
{
my_strcpy(fd,sqlite3_column_text(stmt,2));
return my_atoi(fd);
}
rc=sqlite3_step(stmt);
}
return ONLINEOUT;
}
int read_online_flag(sqlite3*db,char**errmsg,char*user)//用于验证是否禁言
{
int rc;
int i;
char flag[10];
sqlite3_stmt*stmt=NULL;
rc=sqlite3_prepare(db,"select*from online",-1,&stmt,0);
is_sqlite_ok(rc);
rc=sqlite3_step(stmt);
int userflag=1;
while(rc==SQLITE_ROW)
{
userflag=my_strcmp(user,sqlite3_column_text(stmt,1));
if(userflag==0)
{
my_strcpy(flag,sqlite3_column_text(stmt,3));
return my_atoi(flag);
}
rc=sqlite3_step(stmt);
}
return-10;
}
void write_online_all(sqlite3*db,char**errmsg,vpChat temp)//向在线用户发送信息
{
int rc;
int flag;
char fd[100];
sqlite3_stmt*stmt=NULL;
rc=sqlite3_prepare(db,"select*from online",-1,&stmt,0);
is_sqlite_ok(rc);
rc=sqlite3_step(stmt);
int userflag=1;
while(rc==SQLITE_ROW)
{
flag=my_strcmp(temp->name,sqlite3_column_text(stmt,1));
my_strcpy(fd,sqlite3_column_text(stmt,2));
if(flag!=0)
{
write(my_atoi(fd),temp,sizeof(stChat));
}
sleep(1);
rc=sqlite3_step(stmt);
}
}
int update_passwd(sqlite3*db,char**errmsg,char*name,char*passwd)//修改密码
{
int rc;
char sql[1024];
sprintf(sql,"update user set passwd='%s'where name='%s'",passwd,name);
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11