其实这个项目在我电脑已经躺了多时,初写完项目规划后,我认认真真地去实现了它,后来拿着这个项目区参加了面试,同样面试官也拿这个项目来问我,当然我是做过一遍了,而且为了面试,我将什么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);