基于LINUX的多功能聊天室
基于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));
socket编程聊天室基本流程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("\t\t\t\t\t**********************************\n");
printf("\t\t\t\t\t* 欢迎使⽤ *\n");
printf("\t\t\t\t\t* 聊天室服务器 *\n");
printf("\t\t\t\t\t**********************************\n");
}
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 \n",__LINE__);
}
else
{
printf("数据库发⽣错误,请使⽤SQLITE3 看数据库!\n");
printf("sqlite %d error\n",__LINE__);
exit(1);
}
}
void is_sqlite_ok(int rc)
{
if(rc == SQLITE_OK)
{
printf("sqlite %d succse \n",__LINE__);
}
else
{
printf("sqlite %d error\n",__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("数据库已经录⼊完毕\n");
}
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("聊天记录已经录⼊完毕\n");
}
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);
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论