关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » HTML5 »基于Linux的多功能聊天室

    基于Linux的多功能聊天室

    2015-02-03 00:00:00 出处:oschina
    分享

    基于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("ttttt**********************************n");
    	printf("ttttt*      欢迎使用                  *n");
    	printf("ttttt*           聊天室服务器         *n");
    	printf("ttttt**********************************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 errorn",__LINE__);
    		exit(1);
    	}
    }
    
    void is_sqlite_ok(int rc)
    {
        if(rc == SQLITE_OK)
    	{
    	   printf("sqlite %d succse n",__LINE__);
    	}
    	else
    	{
    		printf("sqlite %d errorn",__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++ != '')
    	{
    		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 = %dn",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:%sna",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:%sna",strerror(errno));
    		exit(1);
    	}
    }
    void mylisten(int lfd)// 开始监听端口   等待客户的请求
    {
    	if(listen(lfd,20)==-1)
    	{
    		fprintf(stderr,"Listen error:%sna",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:%sna",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 = %sn",temp.name);
    	printf("passwd = %sn",temp.passwd);
    	printf("cmd = %dn",temp.cmd);
    	printf("revert = %dn",temp.revert);
        printf("toname = %sn",temp.toname);
    	printf("msg = %sn",temp.msg);
    	printf("flag = %dn",temp.flag);
    	printf("sockfd = %dn",temp.sockfd);
    	printf("time = %sn",temp.time);
    	printf("filename = %sn",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("ttt服务器开始等待客户端链接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("%dt",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)] = '';
    					/*打印客户端地址 和 端口号*/
    					printf("客户端的Ip是%s, 端口是 %dn",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 一下,感谢!

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    正版 Windows 11产品密钥怎么查找/查看?

    还有3个月,微软将停止 Windows 10 的更新

    Windows 10 终止支持后,企业为何要立即升级?

    Windows 10 将于 2025年10 月终止技术支持,建议迁移到 Windows 11

    Windows 12 发布推迟,微软正全力筹备Windows 11 25H2更新

    Linux 退出 mail的命令是什么

    Linux 提醒 No space left on device,但我的空间看起来还有不少空余呢

    hiberfil.sys文件可以删除吗?了解该文件并手把手教你删除C盘的hiberfil.sys文件

    Window 10和 Windows 11哪个好?答案是:看你自己的需求

    盗版软件成公司里的“隐形炸弹”?老板们的“法务噩梦” 有救了!

    IT头条

    公安部:我国在售汽车搭载的“智驾”系统都不具备“自动驾驶”功能

    02:03

    液冷服务器概念股走强,博汇、润泽等液冷概念股票大涨

    01:17

    亚太地区的 AI 驱动型医疗保健:2025 年及以后的下一步是什么?

    16:30

    智能手机市场风云:iPhone领跑销量榜,华为缺席引争议

    15:43

    大数据算法和“老师傅”经验叠加 智慧化收储粮食尽显“科技范”

    15:17

    技术热点

    商业智能成CIO优先关注点 技术落地方显成效(1)

    用linux安装MySQL时产生问题破解

    JAVA中关于Map的九大问题

    windows 7旗舰版无法使用远程登录如何开启telnet服务

    Android View 事件分发机制详解

    MySQL用户变量的用法

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。