zoukankan      html  css  js  c++  java
  • 基于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("					**********************************
    ");
    	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);
    	    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,"
    ");      
    	        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,"
    ");      
    	        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++ != '')
    	{
    		len++;
    	}
    	return len;
    }
    int my_strcmp(const char *str1,const char *str2)
    {
    	if(str1 != NULL && str2 != NULL)
    	{
    	}
    	else
    	{
    		return -2;
    	}
    
    	int i;
    	while((*str1)!='' && (*str2) != '')
    	{
    		if((*str1) == (*str2))
    		{
    			str1++;
    			str2++;
    		}
    		else
    		{
    			break;
    		}
    	}
    	if((*str1) == '' && (*str2) == '')
    	{
    		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++)) != '');
    	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 != '')
    	{
    		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) != '')
    	{
    		dest++;
    	}
    	while(((*dest++) = (*src++)) != '');
    	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
    ",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
    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
    a",strerror(errno));
    		exit(1);
    	}
    }
    void mylisten(int lfd)// 开始监听端口   等待客户的请求
    {
    	if(listen(lfd,20)==-1)
    	{
    		fprintf(stderr,"Listen error:%s
    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
    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!
    ");
        }
    }
    
    

    服务器主程序

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

    #include"data.h"
    #include"package.h"
    void display(stChat temp)//用于显示发送命令
    {
    	printf("name = %s
    ",temp.name);
    	printf("passwd = %s
    ",temp.passwd);
    	printf("cmd = %d
    ",temp.cmd);
    	printf("revert = %d
    ",temp.revert);
        printf("toname = %s
    ",temp.toname);
    	printf("msg = %s
    ",temp.msg);
    	printf("flag = %d
    ",temp.flag);
    	printf("sockfd = %d
    ",temp.sockfd);
    	printf("time = %s
    ",temp.time);
    	printf("filename = %s
    ",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("			服务器开始等待客户端链接
    ");
    	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	",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已经成功链接
    ",sfd);
    				n = read(sfd,&temp,sizeof(stChat));
    				if(n == 0)
    				{
    					printf("客户端sfd = %d已经离开本服务器. 
    ",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)] = '';
    					/*打印客户端地址 和 端口号*/
    					printf("客户端的Ip是%s, 端口是 %d
    ",addr_p,ntohs(cin.sin_port));
                        int revert ;
    					revert = cmd_user(db,&errmsg,&temp,sfd);
    					temp.revert = revert;
    					printf("开始向客户端发送命令!
    ");
    				//	printf("以下为命令结构体!
    ");
                     //   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("发送完毕!
    ");
    					memset(&temp,0,sizeof(stChat));//清空发送数据结构体
    					/* 谐函数出错 */
    					if(n == 1)
    					{
    						exit(1);
    					}
    				}
    
    				/*如果没有可以读的套接字   退出循环*/
    				if(--rdy <= 0)
    				{
    					break;
    				}
    
    
    			}
    		}
    
    	}
    
    	close(lfd);       /* 关闭链接套接字 */
    	return 0;
    }
    
    

    项目地址

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

  • 相关阅读:
    7.Flask-上传文件和访问上传的文件
    Python 数字模块
    Django之模板语法
    decimal模块
    python中的计时器:timeit模块
    6.Flask-WTForms
    Django之ORM跨表操作
    公司 邮件 翻译 培训 长难句 16
    公司 邮件 翻译 培训 长难句 15
    公司 邮件 翻译 培训 长难句 14
  • 原文地址:https://www.cnblogs.com/samuelwnb/p/4265519.html
Copyright © 2011-2022 走看看