基于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));
       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);
    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("\n");
                     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);
        rc = sqlite3_exec(db,sql,NULL,NULL,errmsg);
        if(rc == SQLITE_OK)
         {
             return 1;
         }
         else
         {
             return 0;
         }

}
int update_user(sqlite3 *db,char **errmsg,char *name,char *toname)//修改密码
{
         int rc;
         char sql[1024];
         sprintf(sql,"update user set name = '%s'where name = '%s'",toname,name);
        rc = sqlite3_exec(db,sql,NULL,NULL,errmsg);
        if(rc == SQLITE_OK)
         {
             return 1;
         }
         else
         {
             return 0;
         }

}
int update_db_data(sqlite3 *db,char **errmsg,char *name,char *toname)//修改密码
{
         int rc1;
         int rc2;
         char sql[1024];
         sprintf(sql,"update data set name = '%s'where name = '%s'",toname,name);
        rc1 = sqlite3_exec(db,sql,NULL,NULL,errmsg);
        memset(sql,0,1024);
         sprintf(sql,"update data set toname = '%s'where toname = '%s'",toname,name);
        rc2 = sqlite3_exec(db,sql,NULL,NULL,errmsg);
        if(rc1 == SQLITE_OK && rc2 == SQLITE_OK)
         {
             return 1;
         }
         else
         {
             return 0;
         }

}
int update_flag(sqlite3 *db,char **errmsg,char *name,int flag)//禁言解禁操作
{
         int rc;
         char sql[1024];
         sprintf(sql,"update online set flag = %d where name = '%s'",flag,name);
        rc = sqlite3_exec(db,sql,NULL,NULL,errmsg);
        if(rc == SQLITE_OK)
         {
             return 1;
         }
         else
         {
             return 0;
         }
}
int delete_user(sqlite3 *db,char **errmsg,char *name)//注销用户
{
         int rc;
         char sql[1024];
         sprintf(sql,"delete from user where name = '%s'",name);
         rc = sqlite3_exec(db,sql,NULL,NULL,errmsg);
         if(rc == SQLITE_OK)
         {
             return 1;
         }
         else
         {
             return 0;
         }

}
void read_online_all(sqlite3 *db,char **errmsg,vpChat temp)//向在线用户发送信息
{
    int rc;
    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)
    {
            my_strcpy(temp->msg,sqlite3_column_text(stmt,1));
            mywrite(temp);
            sleep(1);   
            rc = sqlite3_step(stmt);
    }
}
void read_data(sqlite3 *db,char **errmsg,vpChat temp)//向在线用户发送信息
{
    int rc;
    char name[80];
    char toname[80];
    sqlite3_stmt *stmt = NULL;
    rc = sqlite3_prepare(db,"select * from data",-1,&stmt,0); 
    is_sqlite_ok(rc);
    rc = sqlite3_step(stmt);
    int userflag = 1;
    while(rc == SQLITE_ROW)
    {
            my_strcpy(name,sqlite3_column_text(stmt,2));
            my_strcpy(toname,sqlite3_column_text(stmt,3));
        if( my_strcmp(temp->name,name) == 0)
        {
            strcat(temp->msg,"你");      
            strcat(temp->msg,"给");      
            strcat(temp->msg,toname);      
            strcat(temp->msg,"发了");      
            strcat(temp->msg,sqlite3_column_text(stmt,4));
            strcat(temp->msg,"\n");      
            my_strcpy(temp->time,sqlite3_column_text(stmt,1));
            mywrite(temp);
            memset(temp->msg,0,sizeof(temp->msg));
            sleep(1);       
        }
        if(my_strcmp(temp->name,toname) == 0)
        {
            strcat(temp->msg,toname);      
            strcat(temp->msg,"给你发了");      
            strcat(temp->msg,sqlite3_column_text(stmt,4));
            strcat(temp->msg,"\n");      
            my_strcpy(temp->time,sqlite3_column_text(stmt,1));
            mywrite(temp);
            memset(temp->msg,0,sizeof(temp->msg));
            sleep(1);       
        }
            rc = sqlite3_step(stmt);
    }
}

这个是数据库的各类操作呢!
那么它的头文件估计也是函数申明

void is_sqlite(int rc);  //测试数据库
void is_malloc_ok(vpChat *list);
void is_sqlite_ok(int rc);
void open_db(sqlite3 **db);//打开数据库
void creat_user_db(sqlite3 *db,char **errmsg);//建立user数据表
void creat_data_db(sqlite3 *db,char **errmsg);//建立data数据表
void creat_online_db(sqlite3 *db,char **errmsg);//建立online数据表
void creat_server_db(sqlite3 *db,char **errmsg);//建立server数据表
void insert_server_db(sqlite3 *db,char *time,char **errmsg);
void read_db_ok(sqlite3 *db,char *errmsg,char*tablename);
void delete_clean_db(sqlite3 *db,char *tablename,char **errmsg);
int read_online_fd(sqlite3 *db,char **errmsg,char *user);
int read_online_flag(sqlite3 *db,char **errmsg,char *user);
void write_online_all(sqlite3 *db,char **errmsg,vpChat temp);
int update_passwd(sqlite3 *db,char **errmsg,char *name,char *passwd);
void insert_data_db(sqlite3 *db,char **errmsg,char *time,vpChat temp);
int update_flag(sqlite3 *db,char **errmsg,char *name,int flag);
int delete_user(sqlite3 *db,char **errmsg,char *name);
void read_online_all(sqlite3 *db,char **errmsg,vpChat temp);
void read_data(sqlite3 *db,char **errmsg,vpChat temp);
int update_user(sqlite3 *db,char **errmsg,char *name,char *toname);
int update_db_data(sqlite3 *db,char **errmsg,char *name,char *toname);

干货来了,string.c

很明显是我为了面试准备所写的函数!经测是有效的!

#include"data.h"
int my_strlen(const char *str)
{
    int len;
    while(*str++ != '\0')
    {
        len++;
    }
    return len;
}
int my_strcmp(const char *str1,const char *str2)
{
    if(str1 != NULL && str2 != NULL)
    {
    }
    else
    {
        return -2;
    }

    int i;
    while((*str1)!='\0' && (*str2) != '\0')
    {
        if((*str1) == (*str2))
        {
            str1++;
            str2++;
        }
        else
        {
            break;
        }
    }
    if((*str1) == '\0' && (*str2) == '\0')
    {
        return 0;
    }
    else
    {
        return (*str1) > (*str2)? 1 : -1;
    }
}
char  *my_strcpy( char *dest,const char *src)
{
    if(dest != NULL && src != NULL)
    {
    }
    else
    {
        return NULL;
    }
    char *adress = dest;
    while(((*dest++) = (*src++)) != '\0');
    return adress;
}
int my_atoi(const char *str)
{
    if(str != NULL)
    {
    }
    else
    {
        return -1;
    }
    const char* p = str;
    int minus = 0;
    long result = 0;
    if(*p == '-')
    {
        minus = 1;
        p++;
    }
    else if(*p == '+')
    {
        p++;
    }
    while(*p != '\0')
    {
        if(*p < '0' || *p >'9')
        {
            return -1;
        }
        result = result*10 + ((*p) - '0');
        p++;
    }
    minus = 1 ? -result:result;
    return result;
}

char * my_strcat(char *dest,const char *src)
{
    if(dest != NULL && src != NULL)
    {
    }
    else
    {
        return NULL;
    }
    char *address = dest;
    while((*dest) != '\0')
    {
        dest++;
    }
    while(((*dest++) = (*src++)) != '\0');
    return address;
}

CMD.c 命令解析

#include"data.h"
int cmd_user(sqlite3 *db,char **errmsg,vpChat temp,int sockfd)//用语判别用户信息
{
    int flag;
    int sayflag;
    printf("cmd = %d\n",temp->cmd);
   switch(temp->cmd )
   {
    case REG:
          {
             flag = read_user(db,errmsg,temp->name);
             if(flag == USERIN)
             {
                 return REGNO;//注册重名
             }
              else
             {
                reg_db(db,errmsg,temp->name,temp->passwd);
                temp->flag = read_id(db,errmsg,temp->name);
                return REGOK;
             }
             break;
          }
     case LOG:
          {
              int flagpasswd;
              flag = read_online_ok(db,errmsg,temp->name);
              if(flag == ONLINEIN)
              {
                  return ONLINEIN;
              }
              else
              {
                  flagpasswd = read_pass(db,errmsg,temp->name,temp->passwd);
                  if(flagpasswd == PASSWDOK)
                  {
                      log_db(db,errmsg,temp->name,sockfd);
                      return PASSWDOK;
                  }
                  else
                  {
                      return PASSWDNO;
                  }
              }
              break;
          }  
     case LOGID:
          {
              int flagpasswd;
              read_id_name(db,errmsg,temp);//询问有无此用户
              flag = read_online_ok(db,errmsg,temp->name);
              if(flag == ONLINEIN)
              {
                  return ONLINEIN;
              }
              else
              {
                  flagpasswd = read_pass(db,errmsg,temp->name,temp->passwd);
                  if(flagpasswd == PASSWDOK)
                  {
                      log_db(db,errmsg,temp->name,sockfd);
                      return PASSWDOK;
                  }
                  else
                  {
                      return PASSWDNO;
                  }
              }
              break;
          }  
      case CHAT:
           {
               int tempfd;
              tempfd = read_online_fd(db,errmsg,temp->toname);
              if(tempfd == ONLINEOUT)
              {
                   return ONLINEOUT;
              }
              else
              {
                  sayflag = read_online_flag(db,errmsg,temp->name); 
                  if(sayflag == 0)
                  {
                      return MYFLAGNO;
                  }
                  else
                  { 
                     temp->flag = flag;
                     temp->sockfd = tempfd;
                     insert_data_db(db,errmsg,temp->time,temp);
                     return CHATOK;
                  }
              }
              break;
           }
      case ALL:
           {
               sayflag = read_online_flag(db,errmsg,temp->name); 
               if(sayflag == 0)
               {

                   return MYFLAGNO;
               }
               else
               {
                   insert_data_db(db,errmsg,temp->time,temp);
                   return ALLOK;
               }
               break;
           }
      case SMILE:
           {
               sayflag = read_online_flag(db,errmsg,temp->name); 
               if(sayflag == 0)
               {
                   return MYFLAGNO;
               }
               else
               {
                     insert_data_db(db,errmsg,temp->time,temp);
                   return SMILEOK;
               }
               break;
           }
       case WELCOME:
           {
               sayflag = read_online_flag(db,errmsg,temp->name); 
               if(sayflag == 0)
               {
                   return MYFLAGNO;
               }
               else
               {
                     insert_data_db(db,errmsg,temp->time,temp);
                   return WELCOMEOK;
               }
               break;
           }
       case PASSWD:
           {
             flag =  update_passwd(db,errmsg,temp->name,temp->passwd);
             return flag;
             break;
           }
       case BOOT:
           {  
              int tempfd;
              tempfd = read_online_fd(db,errmsg,temp->toname);
              if(tempfd == ONLINEOUT)
              {
                   return ONLINEOUT;
              }
              else
              {
                     temp->sockfd = tempfd;
                     return BOOTOK;
              }
              break;
           }
        case STEP:
           {
              int tempfd;
              tempfd = read_online_fd(db,errmsg,temp->toname);
              if(tempfd == ONLINEOUT)
              {
                   return ONLINEOUT;
              }
              else
              {
                     flag =  update_flag(db,errmsg,temp->toname,0);
                     if(flag == 1)
                     {
                        temp->sockfd = tempfd;
                     }
                     return flag;
              }
              break;
           }
        case BAN:
           {

              int tempfd;
              tempfd = read_online_fd(db,errmsg,temp->toname);
              if(tempfd == ONLINEOUT)
              {
                   return ONLINEOUT;
              }
              else
              {
                     sayflag = read_online_flag(db,errmsg,temp->toname); 
                     if(sayflag == 1)
                     {
                         return TOFLAGOK;
                     }
                     else
                     {
                         flag =  update_flag(db,errmsg,temp->toname,1);
                         if(flag == 1)
                         {
                                temp->sockfd = tempfd;
                         }
                         return flag;
                     }
              }
              break;
           }
          case SET:
           {

              int tempfd;
              tempfd = read_online_fd(db,errmsg,temp->toname);
              if(tempfd == ONLINEOUT)
              {
                  flag = delete_user(db,errmsg,temp->toname);
                  return flag;
              }
              else
              {
                  return ONLINEIN;
              }
               break;
           }
          case SEE:
           {
               return SEEOK;
               break;
           }
          case DATA:
           {
               return DATAOK;
               break;
           }
          case SEND:
           {
              int tempfd;
              tempfd = read_online_fd(db,errmsg,temp->toname);
              if(tempfd == ONLINEOUT)
              {
                  return ONLINEOUT;
              }
              else
              {
                   temp->sockfd = tempfd;
                   return SENDOK;
              }
               break;
           }
          case CHANGE:
           {
             flag = read_user(db,errmsg,temp->toname);
             if(flag == USERIN)
             {
                 return REGNO;//注册重名
             }
             else
             {
                 flag = update_user(db,errmsg,temp->name,temp->toname);//¿¿¿¿
                 if(flag == 1)
                 {
                      sayflag = update_db_data(db,errmsg,temp->name,temp->toname);//修改密码
                     return sayflag;
                 }
                 else
                {
                    return 0;
                }
             }
               break;
           }

   }
}

那么它的头文件是估计也是用于申明函数的!

int cmd_user(sqlite3 *db,char **errmsg,vpChat temp,int sockfd);

socket.c文件分析

#include"data.h"
void mybzero(struct sockaddr_in *sin)//对server_addr_in  结构进行赋值
{
    bzero(sin,sizeof(struct sockaddr_in));   /* 先清零 */
    sin->sin_family=AF_INET;                 //
    sin->sin_addr.s_addr=htonl(INADDR_ANY);  //表示接受任何ip地址   将ip地址转换成网络字节序
    sin->sin_port=htons(portnumber);         //将端口号转换成网络字节序
}
int mysocket()//调用socket函数创建一个TCP协议套接口
{
    int lfd;
    if((lfd = socket(AF_INET,SOCK_STREAM,0)) == -1) // AF_INET:IPV4;SOCK_STREAM:TCP
    {
        fprintf(stderr,"Socket error:%s\n\a",strerror(errno));
        exit(1);
    }
    return lfd;
}
void mybind(int lfd,struct sockaddr_in *sin)    // 调用bind函数 将serer_addr结构绑定到sockfd上 
{
    if(bind(lfd,(struct sockaddr *)(sin),sizeof(struct sockaddr))==-1)
    {
        fprintf(stderr,"Bind error:%s\n\a",strerror(errno));
        exit(1);
    }
}
void mylisten(int lfd)// 开始监听端口   等待客户的请求
{
    if(listen(lfd,20)==-1)
    {
        fprintf(stderr,"Listen error:%s\n\a",strerror(errno));
        exit(1);
    }
}
int myaccept(int lfd,struct sockaddr_in *cin,socklen_t * addr_len)// 接受客户端的请求 
{
    int cfd;
    if((cfd=accept(lfd,(struct sockaddr *)cin,addr_len))==-1)
    {
        fprintf(stderr,"Accept error:%s\n\a",strerror(errno));
        exit(1);
    }
    return cfd;
}
void mywrite(vpChat temp)
{
    int num;
    if((num = write(temp->sockfd,temp,sizeof(stChat))) == -1)
    {
        printf("send error!\n");
    }
}

服务器主程序

朱程序里面主要是打开数据库,初始化数据库,及用于显示数据库的命令,下面为代码部分

#include"data.h"
#include"package.h"
void display(stChat temp)//用于显示发送命令
{
    printf("name = %s\n",temp.name);
    printf("passwd = %s\n",temp.passwd);
    printf("cmd = %d\n",temp.cmd);
    printf("revert = %d\n",temp.revert);
    printf("toname = %s\n",temp.toname);
    printf("msg = %s\n",temp.msg);
    printf("flag = %d\n",temp.flag);
    printf("sockfd = %d\n",temp.sockfd);
    printf("time = %s\n",temp.time);
    printf("filename = %s\n",temp.filename);
}
int main()
{
    time_t timep;
    time(&timep);
    char *timedata = ctime(&timep);
    sqlite3 *db = NULL;
    char *errmsg;
    open_db(&db);//打开数据库
    creat_user_db(db,&errmsg);
    creat_data_db(db,&errmsg);
    creat_online_db(db,&errmsg);
    creat_server_db(db,&errmsg);
    insert_server_db(db,timedata,&errmsg);//向server数据库插入数据
    insert_server();
    int  lfd;
    int cfd;
    int sfd;
    int rdy;
    stChat temp;
    struct sockaddr_in sin;
    struct sockaddr_in cin;
    int client[FD_SETSIZE];  /* 客户端连接的套接字描述符数组 */
    int maxi;
    int maxfd;                        /* 最大连接数 */
    fd_set rset;
    fd_set allset;
    socklen_t addr_len;         /* 地址结构长度 */
    int i;
    int n;
    int len;
    int opt = 1;   /* 套接字选项 */
    char addr_p[20];
    mybzero(&sin);
    lfd = mysocket();
    /*设置套接字选项 使用默认选项*/
    setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
    mybind(lfd,&sin);   // 调用bind函数 将serer_addr结构绑定到sockfd上 
    mylisten(lfd);// 开始监听端口   等待客户的请求
    printf("\t\t\t服务器开始等待客户端链接\n");
    maxfd = lfd;                                /*对最大文件描述符进行初始化*/
    maxi = -1;
    /*初始化客户端连接描述符集合*/
    for(i = 0;i < FD_SETSIZE;i++)
    {
        client[i] = -1;
    }

    FD_ZERO(&allset);                     /* 清空文件描述符集合 */
    FD_SET(lfd,&allset);                    /* 将监听字设置在集合内 */
    /* 开始服务程序的死循环 */
    while(1)
    {
        rset = allset;
        
        /*得到当前可以读的文件描述符数*/
        rdy = select(maxfd + 1, &rset, NULL, NULL, NULL);
        
        if(FD_ISSET(lfd, &rset))
        {
        
            addr_len = sizeof(sin);
            cfd = myaccept(lfd,&cin,&addr_len);// 接受客户端的请求 
            /*查找一个空闲位置*/
            for(i = 0; i<FD_SETSIZE; i++)
            {       //printf("%d\t",client[i]);
                if(client[i] <= 0)
                {
                    client[i] = cfd;   /* 将处理该客户端的连接套接字设置到该位置 */
                    break;
                }
            }

        /* 太多的客户端连接   服务器拒绝俄请求  跳出循环 */
            if(i == FD_SETSIZE)
            {
                printf("too many clients");
                exit(1);
            }

            FD_SET(cfd, &allset);     /* 设置连接集合 */

            if(cfd > maxfd)                  /* 新的连接描述符 */
            {
                maxfd = cfd;
            }

            if(i > maxi)
            {
                maxi = i;
            }

            if(--rdy <= 0)                /* 减少一个连接描述符 */
            {
                continue;
            }

        }
        
        /* 对每一个连接描述符做处理 */
        for(i = 0;i< FD_SETSIZE;i++)
        {   
            if((sfd = client[i]) < 0)
            {
                continue;
            }

            if(FD_ISSET(sfd, &rset))
            {
                printf("客户端sfd = %d已经成功链接\n",sfd);
                n = read(sfd,&temp,sizeof(stChat));
                if(n == 0)
                {
                    printf("客户端sfd = %d已经离开本服务器. \n",sfd);
                    delete_online_db(db,&errmsg,sfd);
                    fflush(stdout);                                    /* 刷新 输出终端 */
                    close(sfd);
                    FD_CLR(sfd, &allset);                        /*清空连接描述符数组*/
                    client[i] = -1;
                }
                else
                {
                    temp.sockfd = sfd;
                    /* 将客户端地址转换成字符串 */
                    inet_ntop(AF_INET, &cin.sin_addr, addr_p, sizeof(addr_p));
                    addr_p[strlen(addr_p)] = '\0';
                    /*打印客户端地址 和 端口号*/
                    printf("客户端的Ip是%s, 端口是 %d\n",addr_p,ntohs(cin.sin_port));
                    int revert ;
                    revert = cmd_user(db,&errmsg,&temp,sfd);
                    temp.revert = revert;
                    printf("开始向客户端发送命令!\n");
                //  printf("以下为命令结构体!\n");
                 //   display(temp);
                    if(revert < 5)
                    {  
                         mywrite(&temp);
                    }
                    else if(revert == DATAOK)
                    {
                        read_data(db,&errmsg,&temp);//向在线用户发送信息
                    }
                    else if(revert == SEEOK)
                    {
                         read_online_all(db,&errmsg,&temp);//向在线用户发送信息
                    }
                    else if(revert == ALLOK || revert == SMILEOK || revert == WELCOMEOK)
                    {
                         write_online_all(db,&errmsg,&temp);
                    }
                    printf("发送完毕!\n");
                    memset(&temp,0,sizeof(stChat));//清空发送数据结构体
                    /* 谐函数出错 */
                    if(n == 1)
                    {
                        exit(1);
                    }
                }

                /*如果没有可以读的套接字   退出循环*/
                if(--rdy <= 0)
                {
                    break;
                }


            }
        }

    }

    close(lfd);       /* 关闭链接套接字 */
    return 0;
}

项目地址

其实它就在我的github里面。你可怜点击链接进入,当然希望您在看的过程中能够followe me 一下,感谢!

转载于:https://www.cnblogs.com/samuelwnb/p/4265519.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值