免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3440 | 回复: 18
打印 上一主题 下一主题

[C] 没事的都来 P 我的 . 我现在很闲. [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-01-03 09:51 |只看该作者 |倒序浏览
小弟最近写的一个统计游戏玩家,在线时间的程序,
会有很多不足之处,请高手指点.


/*
* =====================================================================================
*
*       Filename:  online_time.h
*
*    Description:
*
*        Version:  1.0
*        Created:  2007年12月29日 15时17分59秒 CST
*       Revision:  none
*       Compiler:  gcc
*
*         Author:  liping (fl), lxy9805287@163.com
*        Company:  Free company
*
* =====================================================================================
*/
#include        <stdio.h>
#include        <stdlib.h>
#include        <errno.h>
#include        <string.h>
#include        <mysql/mysql.h>

#ifdef  s8
#undef  s8                      /*  */
#else      /* -----  not u8  ----- */
#define s8  char                /*  */
#endif     /* -----  not u8  ----- */
#ifdef  u8
#undef  u8                      /*  */
#else      /* -----  not u8  ----- */
#define u8 unsigned char        /*  */
#endif     /* -----  not u8  ----- */
#ifdef  s16
#undef  s16                     /*  */
#else      /* -----  not s16  ----- */
#define s16 signed short                        /*  */
#endif     /* -----  not s16  ----- */
#ifdef  u16
#undef  u16                     /*  */
#else      /* -----  not u16  ----- */
#define u16 unsigned short      /*  */
#endif     /* -----  not u16  ----- */
#ifdef  s32
#undef  s32                     /*  */
#else      /* -----  not s32  ----- */
#define s32 signed int          /*  */
#endif     /* -----  not s32  ----- */
#ifdef  u32
#undef  u32                     /*  */
#else      /* -----  not u32  ----- */
#define u32 unsigned int        /*  */
#endif     /* -----  not u32  ----- */
#ifdef  u64
#undef  u64                     /*  */
#else      /* -----  not u64  ----- */
#define u64 unsigned long long
#endif     /* -----  not u64  ----- */
#define ElmeType        int     /*  */
MYSQL mysql;
MYSQL_RES *res;
struct  Name{                                   /* 记录玩家帐号 */
        s8      *Account;
        s8      IpAddress[16];                       /* 玩家地址 */
        struct  Name *next;
};
struct  PlayerInfo{
        s8  *Account;                            /* 帐号 */
        u64 LoginTimeCount;                     /* 登入时间和 */
        u64 LogoutTimeCount;                    /* 登出时间和 */
        u64 RealOnlineTime;
};
MYSQL mysql;
MYSQL_RES *res;
struct  Name{                                   /* 记录玩家帐号 */
        s8      *Account;
        s8      IpAddress[16];                       /* 玩家地址 */
        struct  Name *next;
};
struct  PlayerInfo{
        s8  *Account;                            /* 帐号 */
        u64 LoginTimeCount;                     /* 登入时间和 */
        u64 LogoutTimeCount;                    /* 登出时间和 */
        u64 RealOnlineTime;
};
struct Config {
        char    DbHost[20];
        char    DbUser[20];
        char    DbPass[20];
        char    DbName[20];
        char    PastTm[3];
};                              /* ----------  end of struct SqlConf  ---------- */
typedef struct  Name PlayerAccount;
typedef struct  PlayerInfo PlayerDetail;
typedef struct  {
        PlayerAccount *front;
        PlayerAccount *rear;
}PlayerAccountQueue;
extern PlayerAccountQueue    *InitAccountQueue(PlayerAccountQueue *PlayerList); /* 初始化队列 */
extern int EmptyQueue(PlayerAccountQueue *PlayerList); /* 判断队列是否为空 */
extern PlayerAccountQueue    *CreateAccountQueue(PlayerAccountQueue *PlayerList,char *account,char *IpAddress); /* 创建链式队列 */
extern int OutAccountQueue(PlayerAccountQueue *PlayerList,char Account[],char *IpAddress); /* 出队 */
extern MYSQL_RES  *GetMysqlData(char *query);   /* 执行mysql查询 */
extern int OpenMysqlConnect(void *config);              /* 创建mysql连接 */
extern void   get_time ( int PastTm ,char the_time[] );            /*  */
extern time_t MkPathTime (int PastTm, time_t timep,int hour,int min,int sec );
extern struct  Config  *GetConfig(char *cfg_name,struct  Config *db);

[[i] 本帖最后由 lxy9805287 于 2008-1-7 16:58 编辑 [/i]]

StatLog.tar.gz

5.79 KB, 下载次数: 37

论坛徽章:
0
2 [报告]
发表于 2008-01-03 09:53 |只看该作者
/*
* =====================================================================================
*
*       Filename:  online_time.c
*
*    Description:
*
*        Version:  1.0
*        Created:  2007年12月29日 15时17分59秒 CST
*       Revision:  none
*       Compiler:  gcc
*
*         Author:  liping (fl), lxy9805287@163.com
*        Company:  Free company
*
* =====================================================================================
*/
#include        "online_time.h"
#include        <time.h>

#define LOGIN_SQL       "SELECT UNIX_TIMESTAMP(LoginTime) FROM player_action where LoginTime >= '%s 00:00:00' and \
        LoginTime <= '%s 23:59:59' and PlayerAccount ='%s' and Action='Login' order by LoginTime"                       /*  */
#define LOGOUT_SQL      "SELECT UNIX_TIMESTAMP(LoginTime) FROM player_action where LoginTime >= '%s 00:00:00' and \
        LoginTime <= '%s 23:59:59' and PlayerAccount ='%s' and Action='Logout' order by LoginTime"                      /*  */

#define CREATE_LIST     "SELECT PlayerAccount,LoginIp FROM player_action where LoginTime >= '%s 00:00:00' and  \
                LoginTime <= '%s 23:59:59'  and LoginIp is NOT NULL group by PlayerAccount"

#define CONFIG  "db.cfg"                        /*  */
#define LOGNAME "run.log"               /* 程序的运行日志 */
int main ( int argc, char *argv[] )
{
        time_t  timep;
        static u64      LoginPatchTime;
        static u64      LogoutPatchTime;
        int     PastTm;
        PlayerAccountQueue      PlayerList;
        PlayerAccountQueue      *PlayerQueue;
        PlayerDetail    PlayerOnlineInfo;
        MYSQL_ROW       row;
        MYSQL_ROW       LoginRow;
        MYSQL_ROW       LogoutRow;
        MYSQL_RES       *Res_t;
        MYSQL_RES       *result;
        MYSQL_RES       *LoginRes;
        MYSQL_RES       *LogoutRes;
        s8      IpAddress[18];
        u16     LoginNumRows;
        u16     LogoutNumRows;
        s8      Account[40];
        s8      sql[1024];
        s8      yesterday[12];
        FILE    *RunLog;
        RunLog = fopen (LOGNAME,"a");
        // 读取配置mysql文件,包括统计几天前的日志
        struct  Config *my,cf;
        my = GetConfig(CONFIG,&cf);
        PastTm=atoi(my->PastTm);
        if(PastTm < 0 ){                        /* 如果间隔时间错误,默认置为1天 */
                PastTm = 1;
        }
        get_time(PastTm,yesterday);
        PlayerQueue=InitAccountQueue(&PlayerList); /* 初始化队列 */
        if(!OpenMysqlConnect(my)){                /* 打开数据库连接 */
                fprintf(RunLog,"%s  [%d] Open Mysql Error %s\n",argv[0],(int)time(&timep),mysql_error(&mysql));
                fprintf(RunLog,"%s  [%d] Exiting\n",argv[0],(int)time(&timep));
                exit(1);
        }
        //生成 时间,用来补登录和登出
        LoginPatchTime = (u64)MkPathTime(PastTm,timep,0,0,0); /* 00:00:00 */
        LogoutPatchTime = (u64)MkPathTime(PastTm,timep,23,59,59); /* 23:59:59 */
        //提取用户帐号  (唯一帐号)
        sprintf(sql,CREATE_LIST,yesterday,yesterday);
        result = GetMysqlData(sql);
        if(result){
                while((row = mysql_fetch_row(result)))
                        if(row[0] && row[1]){
                                PlayerQueue=CreateAccountQueue(PlayerQueue,row[0],row[1]); /* 创建玩家帐号队列 */
                        }
                mysql_free_result(result);
        }
        //主 计算程序
        while(PlayerQueue->front!=NULL){
                memset(sql,0,sizeof(sql));
                if(!OutAccountQueue(PlayerQueue,Account,IpAddress)){    /* 出对,将用户帐号付给 Account 字符篡变量*/
                        fprintf(RunLog,"%s  [%d] Queue is null or PlayerAccount empty \n",argv[0],(int)time(&timep));
                        fprintf(RunLog,"%s  [%d] Exiting\n",argv[0],(int)time(&timep));
                        exit(0);
                }
                sprintf(sql,LOGIN_SQL,yesterday,yesterday,Account);
                LoginRes = GetMysqlData(sql);
                if(!LoginRes)
                        continue;
                Res_t = GetMysqlData(sql);
                LoginNumRows = (u16)mysql_num_rows(Res_t); /* 获取登录的记录行数 */
                LoginRow = mysql_fetch_row(Res_t);

                sprintf(sql,LOGOUT_SQL,yesterday,yesterday,Account);
                LogoutRes = GetMysqlData(sql);
                if(!LogoutRes)
                        continue;
                Res_t = GetMysqlData(sql);
                LogoutNumRows = (u16)mysql_num_rows(Res_t); /* 获取登出的记录行数 */
                LogoutRow = mysql_fetch_row(Res_t);

                PlayerOnlineInfo.LoginTimeCount =0;
                PlayerOnlineInfo.LogoutTimeCount = 0;
                PlayerOnlineInfo.RealOnlineTime = 0;
                if( LoginNumRows == LogoutNumRows ){ /* 登录和退出次数匹配 */
                        if( atol(LoginRow[0]) < atol(LogoutRow[0]) ){ /* 先退出在上线,最后没有下线 */
                                while((row = mysql_fetch_row(LoginRes))){
                                        PlayerOnlineInfo.LoginTimeCount += atol(row[0]);
                                }
                                while((row = mysql_fetch_row(LogoutRes))){
                                        PlayerOnlineInfo.LogoutTimeCount += atol(row[0]);
                                }
                                PlayerOnlineInfo.RealOnlineTime = PlayerOnlineInfo.LogoutTimeCount - PlayerOnlineInfo.LoginTimeCount;
                                sprintf(sql,"INSERT INTO player_onlinetime values('%s','%llu','%s','%s')" \
                                                ,Account,PlayerOnlineInfo.RealOnlineTime,IpAddress,yesterday);
                                mysql_real_query(&mysql,sql,strlen(sql));
                        }else{          /* 先上线,最后下线 */
                                while((row = mysql_fetch_row(LoginRes))){
                                        PlayerOnlineInfo.LoginTimeCount += atol(row[0]);
                                }
                                PlayerOnlineInfo.LoginTimeCount += LoginPatchTime; /* 补一次登录时间 当天00:00:00 */
                                while((row = mysql_fetch_row(LogoutRes))){
                                        PlayerOnlineInfo.LogoutTimeCount += atol(row[0]);
                                }
                                PlayerOnlineInfo.LogoutTimeCount += LogoutPatchTime; /* 补一次登出时间  当天23:59:59 */
                                PlayerOnlineInfo.RealOnlineTime = PlayerOnlineInfo.LogoutTimeCount - PlayerOnlineInfo.LoginTimeCount;
                                sprintf(sql,"INSERT INTO player_onlinetime values('%s','%llu','%s','%s')" \
                                                ,Account,PlayerOnlineInfo.RealOnlineTime,IpAddress,yesterday);
                                mysql_real_query(&mysql,sql,strlen(sql));
                        }
                }else if (LoginNumRows + 1 == LogoutNumRows){   /* 玩家是前00点以前上线,今天下线 */
                        while((row = mysql_fetch_row(LoginRes))){
                                PlayerOnlineInfo.LoginTimeCount += atol(row[0]);
                        }
                        PlayerOnlineInfo.LoginTimeCount += LoginPatchTime;      /* 补一次登录时间 当天00:00:00 */
                        while((row = mysql_fetch_row(LogoutRes))){
                                PlayerOnlineInfo.LogoutTimeCount += atol(row[0]);
                        }
                        PlayerOnlineInfo.RealOnlineTime = PlayerOnlineInfo.LogoutTimeCount - PlayerOnlineInfo.LoginTimeCount;
                        sprintf(sql,"INSERT INTO player_onlinetime values('%s','%llu','%s','%s')" \
                                        ,Account,PlayerOnlineInfo.RealOnlineTime,IpAddress,yesterday);
                        mysql_real_query(&mysql,sql,strlen(sql));
                }else if (LoginNumRows - 1 == LogoutNumRows){   /* 玩家今天上线,24点之前没有下线 */
                        while((row = mysql_fetch_row(LoginRes))){
                                PlayerOnlineInfo.LoginTimeCount += atol(row[0]);
                        }
                        while((row = mysql_fetch_row(LogoutRes))){
                                PlayerOnlineInfo.LogoutTimeCount += atol(row[0]);
                        }
                        PlayerOnlineInfo.LogoutTimeCount += LogoutPatchTime;    /* 补一次登出时间  当天23:59:59 */
                        PlayerOnlineInfo.RealOnlineTime = PlayerOnlineInfo.LogoutTimeCount - PlayerOnlineInfo.LoginTimeCount;
                        sprintf(sql,"INSERT INTO player_onlinetime values('%s','%llu','%s','%s')" \
                                        ,Account,PlayerOnlineInfo.RealOnlineTime,IpAddress,yesterday);
                        mysql_real_query(&mysql,sql,strlen(sql));
                }else{
                        fprintf(RunLog,"%d  %s: Status unknown \n",(int)time(&timep),Account);
                }
                mysql_free_result(LoginRes);
                mysql_free_result(LogoutRes);
        }               /* ----------  end of function main  ---------- */
        mysql_close(&mysql);
        return EXIT_SUCCESS;
}

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
3 [报告]
发表于 2008-01-03 09:54 |只看该作者
日志统计……
哦!蚂蚁够得!
用 Perl 估计一行就搞定了。

论坛徽章:
0
4 [报告]
发表于 2008-01-03 09:54 |只看该作者
/*
* =====================================================================================
*
*       Filename:  database.c
*
*    Description:
*
*        Version:  1.0
*        Created:  2007年12月29日 17时36分04秒 CST
*       Revision:  none
*       Compiler:  gcc
*
*         Author:  liping (fl), lxy9805287@163.com
*        Company:  Free company
*
* =====================================================================================
*/
#include        "online_time.h"
#include        <syslog.h>

int     OpenMysqlConnect(void *config){

        struct  Config *my;
        my = (struct Config *)config;
        if(mysql_init(&mysql)==NULL){
                syslog(LOG_INFO,"Initializtion MySQL error\n");
                return(0);
        }
        if(mysql_real_connect(&mysql,my->DbHost,my->DbUser,my->DbPass,my->DbName,0,NULL,CLIENT_MULTI_STATEMENTS)==NULL){
                syslog(LOG_INFO,"Connect MySQL %s error: %s\n",my->DbHost,mysql_error(&mysql));
                return(0);
        }
        mysql_query(&mysql,"set names gbk");
        return(1);
}
MYSQL_RES       *GetMysqlData(char *query){
        if(mysql_real_query(&mysql,query,strlen(query))!=0){
                syslog(LOG_INFO,"Execute MySQL query error: %s\n",mysql_error(&mysql));
                return(NULL);
        }
        res = mysql_store_result(&mysql);
        if(res)
                return(res);
        return(NULL);
}

论坛徽章:
0
5 [报告]
发表于 2008-01-03 09:55 |只看该作者
/*
* =====================================================================================
*
*       Filename:  config.c
*
*    Description:
*
*        Version:  1.0
*        Created:  2007年12月04日 10时18分20秒 CST
*       Revision:  none
*       Compiler:  gcc
*
*         Author:  liping (fl), lxy9805287@163.com
*        Company:  Free company
*
* =====================================================================================
*/

#include        "online_time.h"
#define SIZE    256                     /*  */

struct  Config  *GetConfig(char *cfg_name,struct  Config *db){
        char    buf[SIZE];
        db =(struct  Config *)malloc(sizeof(struct Config));
        char    *p,*ptr;
        FILE    *fp;                                                                            /* input-file pointer */
        fp      = fopen( cfg_name, "r" );
        if ( fp == NULL ) {
                fprintf ( stderr, "couldn't open file '%s'; %s\n",
                                cfg_name, strerror(errno) );
                return (NULL);
        }
        while ( (fgets(buf,SIZE,fp))!=NULL) {
                if(*buf=='#')
                        continue;
                if(p=strstr(buf,"dbhost")){
                        strcpy(db->DbHost,p+7);
                        if(p=strchr(db->DbHost,'\n')){
                                db->DbHost[p - db->DbHost]='\0';
                        }
                }
                if(p=strstr(buf,"dbuser")){
                        strcpy(db->DbUser,p+7);
                        if(p=strchr(db->DbUser,'\n')){
                                db->DbUser[p - db->DbUser]='\0';
                        }
                }
                if(p=strstr(buf,"dbpass")){
                        strcpy(db->DbPass,p+7);
                        if(p=strchr(db->DbPass,'\n')){
                                db->DbPass[p - db->DbPass]='\0';
                        }
                } else if(p=strstr(buf,"dbname")){
                        strcpy(db->DbName,p+7);
                        if(p=strchr(db->DbName,'\n')){
                                db->DbName[p - db->DbName]='\0';
                        }
                } else if(p=strstr(buf,"PastTm")){
                        strcpy(db->PastTm,p+7);
                        if(p=strchr(db->PastTm,'\n')){
                                db->PastTm[p - db->PastTm]='\0';
                        }
                }
        }
        if( fclose(fp) == EOF ) {                       /* close input file   */
                fprintf ( stderr, "couldn't close file '%s'; %s\n",
                                cfg_name, strerror(errno) );
                //return (EXIT_FAILURE);
        }
        return(db);
}

论坛徽章:
0
6 [报告]
发表于 2008-01-03 09:55 |只看该作者
原帖由 lxy9805287 于 2008-1-3 09:51 发表
小弟最近写的一个统计游戏玩家,在线时间的程序,
会有很多不足之处,请高手指点.


/*
* =====================================================================================
*
*       Filename ...



提个小小的建议:


不要用 #define s8 char 如何 ? 我年纪大,看着这么多重复的东西眼睛花
  
这样可好?

#include <stdint.h>

然后使用c99规范里的:
uint8_t
int8_t
int32_t
uint32_t
int64_t
......

论坛徽章:
0
7 [报告]
发表于 2008-01-03 09:56 |只看该作者
/*
* =====================================================================================
*
*       Filename:  queue.c
*
*    Description:
*
*        Version:  1.0
*        Created:  2007年12月30日 12时38分19秒 CST
*       Revision:  none
*       Compiler:  gcc
*
*         Author:  liping (fl), lxy9805287@163.com
*        Company:  Free company
*
* =====================================================================================
*/
#include        "online_time.h"
PlayerAccountQueue      *InitAccountQueue(PlayerAccountQueue *PlayerList){
        PlayerList = (PlayerAccountQueue*)malloc(sizeof(PlayerAccountQueue));
        PlayerList->front=PlayerList->rear=NULL;
        return(PlayerList);
}                                               /* 初始化 链式队列 */
int     EmptyQueue(PlayerAccountQueue *PlayerList){
        return((PlayerList->rear==NULL)?1:0);
}
PlayerAccountQueue      *CreateAccountQueue(PlayerAccountQueue *PlayerList,char *account,char *IpAddress){
        PlayerAccount *new=NULL;
        new = (PlayerAccount*)malloc(sizeof(PlayerAccount));
        new->Account=(char*)malloc(sizeof(char)*strlen(account)+1);
        if(new->Account==NULL){                    /* 内存分配失败返回空指针 */
                printf("Malloc new->Account Error: %s\n",strerror(errno));
                return(NULL);
        }
        strcpy(new->Account,account);
        strcpy(new->IpAddress,IpAddress);
        new->next=NULL;
        if(PlayerList->rear==NULL)
                PlayerList->front=PlayerList->rear=new;
        else{
                PlayerList->rear->next=new;
                PlayerList->rear=new;
        }
        return(PlayerList);
}                                               /* 创建 链式队列*/
int     OutAccountQueue(PlayerAccountQueue *PlayerList,char Account[],char *IpAddress){
        PlayerAccount *curr;
        if(PlayerList->rear==NULL)
                return(0);
        curr=PlayerList->front;
        if(PlayerList->front==PlayerList->rear)
                PlayerList->front=PlayerList->rear=NULL;
        else
                PlayerList->front=PlayerList->front->next;
        strcpy(Account ,curr->Account);
        strcpy(IpAddress ,curr->IpAddress);
        if(Account!=NULL)
                return(1);
        else
                return(0);
}                                               /* 取出队列元素 */

论坛徽章:
0
8 [报告]
发表于 2008-01-03 09:57 |只看该作者
呵呵,还没发完.老大就跟上了,

论坛徽章:
0
9 [报告]
发表于 2008-01-03 10:13 |只看该作者
多谢,c99 我在仔细看看,
老大给批批. 设计思路和方法是否得当,
从数据库里取出当前的唯一玩家帐号, 存入队列,然后在将帐号出队,查询玩家的登录和登出次数,以及比对当前第一个动作是Login还是Logout  ,

付伪代码,帮忙分析下.

if ( 登入次数  == 登出次数 ) {
         if( 第一次登入时间在第一次登出时间 之后){
                补一次登入时间 (当天 00:00:00);
                补一次登出时间 (当天 23:59:59);
                登出的unix时间和  - 登入的unix时间和  = 当天在线秒数;
                return;
        }
        登出的unix时间和 - 登入的unix时间和 = 在线秒数;
        return;
}else if ( 登入次数 + 1 == 登出次数 ){

        补一次登入时间 (当天 00:00:00);
        登出的unix时间秒数和 - 登入的unix时间秒数和  = 当天在线秒数;
        return;
        
}else if ( 登入次数 -1  == 登出次数 ){
         补一次登出时间 (当天 23:59:59);
        登出的unix时间和  - 登入的unix时间和 = 当天在线秒数;
        return;
}else{  
        日志坏 ;
        逐条记录处理;
        return;
}

论坛徽章:
0
10 [报告]
发表于 2008-01-07 16:57 |只看该作者
我把我的也顶上来, 高手来批批我的,  说我脑子养鱼 我都不介意, 只要能让我认识到错误
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP