Beta版本展示博客

1 团队介绍

团队组成:

齐爽爽(258)个人博客:http://www.cnblogs.com/shuangshuangblog/

马帅(248)个人博客:http://www.cnblogs.com/whu-mashuai/

何健(267)个人博客:http://www.cnblogs.com/hankin2017/

蔡凯峰(285)个人博客:http://www.cnblogs.com/cai2017282110285/

团队Git链接:https://github.com/WHUSE2017/C-team

2 Bate过程回顾

2.1 团队项目目标

(1)预期典型用户:18--40岁在武汉的人,前期只在武汉大学,武大学生。

(2)预期功能描述:能够发布自己的活动行程、搜索到某时间某地点的活动及参加人员信息。

(3)预期用户数量:前期500人左右。

2.2 如何满足用户需求

  只要是本系统的用户,我们都提供活动查询,不过是一件想好取得地点,或者没有想好干什么,但是有时间,都能在系统里面找到想要的信息,即使当时没有找到,你也可以自己做主,发布行程消息,等待其他人的加入。至少我们提供一个集中的平台,更易于找到想找到的人。

  像正常软件一样,用户登录自己的账户,可以直接查看自己的活动行程,也可以点击取消自己的活动,当然,用户最好给系统一个反馈,好让系统的信息更准确。

2.3 分工与经验教训

  我们分工依然比较粗暴的,

  前台界面:何健;

  逻辑层:蔡凯峰;

  数据库设计与连接以及Alpha版展示与讲解:马帅;

  文档编辑与组员协作:齐爽爽。

  经验教训:

  (1)面对面沟通:依然是加强沟通。因为这个周末,大家都有事情,所以小组会议移交在网上,还是没有面对面来的实在。

  (2)还想用《构建之法》里面的那段:>scrum计划阶段的估计不是一个"合同",领导们不要把它当成一个合同。估计总是不准的。坚持短期的sprint,这样即使不准的估计也不会又打的损害。真的觉得敏捷的sprint还是很有效的。

2.4 项目管理

  项目管理就是按照老师上课讲的和书上讲的大概中和一下,分工明确,各自领取任务,然后每天汇报。然后具体修改文档发到讨论组。

2.5 如何做到如期交付

  有计划。主要在前期老师给了两周时间来做分析,把思路计划都已经做好了,所以在冲刺阶段,基本按照前期计划走,有一个计划在那里,所以每天看着燃尽图都有种“革命尚未成功,同志仍需努力”的紧迫感。

  还有小组成员也都很负责。虽然老师任务也很重,但是能熬夜做项目,即使最后交付的东西还不够完善,但是至少能做到,既然咱们干这个事情,就要负责,在规定时间完成自己的任务。

3 燃尽图

  在上次,是木真正的会使用leangoo,后期修改了时间,所以会有偏差,这次一开始就设置好了所有参数,所以还很很准确的显示了项目完成度,因为全部都没有在计划内完成..........于是在最后一天疯狂的解决问题。

4 留给后面小组的说明

项目文件:

 

文件说明:

1.SQLStruct.h

定义了与数据库操作相关的一些结构体:

struct userStruct;    //用户信息
struct EventStruct;    //事件信息
struct StationMessageStruct;    //站内信
struct ParticipantsStrcut;    //事件参与
struct SecretSecurityStruct;    //密保
1

2.Operate.h/Operate.cpp

与数据库进行交互的类,类的定义如下:

class Operate {
public:
    Operate();

    string IntToString(int variable); 
    int StringToInt(string variable);

    bool InsertIntoUserTable(userStruct User);    
    bool InsertIntoEventTable(EventStruct Event);    
    bool InsertIntoStationMessageable(StationMessageStruct StationMessage);
    bool UpdateUserTable(userStruct User);//修改用户信息
    bool UpdatePassword(string UserName, string Password);    //修改密码
    bool InsertIntoSecretSecurity(SecretSecurityStruct Security);    //添加密保
    bool joinEvent(int EventID, string username);    //加入活动
    bool setEventState(int Eventid, int State);//设置活动状态    
    SecretSecurityStruct GetSecretSecurity(string UserName);     //获取密保

    bool DeleteDataParticipants(int EventID, string UserName);//删除Participants中特定数据

    vector<userStruct> LikeUserName(string username);//模糊查找用户名

    vector<ParticipantsStrcut> GetParticipantsByUsername(string Username);
    vector<EventStruct> getEventByCondition(string publisher, string participant, int state);
//查看已发布,或已加入的活动
    string GetPasswordFromUserTable(string username);
    userStruct GetUserDetails(string username);        //获取用户信息
    vector<EventStruct> GetEvent(string StartSite, string EndSite, string StartTime, string EventType);    //搜索活动信息
    vector<EventStruct> GetEventByState(int State);//通过活动状态查询活动
    vector<EventStruct> GetEventByLike(string StartSite, string EndSite);//开始地和结束地模糊查询
    vector<string> GetParticipants(int EventId);//获取活动的参与者
    
    vector<StationMessageStruct> GetMessageBySender(string SenderName);
    vector<StationMessageStruct> GetMessageByReceiver(string ReceiverName);
    EventStruct GetEventDetailById(int EventId);
public:
    MYSQL mydata;
};
2

3.socket_stream.h/socket_stream.cpp

处理socket流数据的类,定义如下:

class socket_stream{
public:
    enum 
    {
        disconnected,
        connected,
    };    //用来判断socket状态的enum值
    socket_stream(char *ip,unsigned short port);    //客户端构造函数,指定要连接                                                //的远程主机的ip,port
    socket_stream(SOCKET s,sockaddr_in * lpremoteAddr = NULL,int nAddrlen=0);
//服务端构造函数,将监听到的socket连接传进来,剩下的两个参数
//可以用来获取socket连接的其他信息
    ~socket_stream();        //析构函数,有些东西需要在这释放掉
    int recvData(char *buffer, int buflen, int flag =0);    //接收流数据
    int sendData(char *buffer, int buflen, int flag =0);    //发送流数据
    int getState();    //获取当前连接的状态
private:
    void init_cs();    //CRITICAL_SECTION初始化CRITICAL_SECTION结构
    SOCKET sock;    
    int state;
    CRITICAL_SECTION send_cs;    //这两个变量用来锁住对读写缓冲区的操作,避免多个线程同时
    CRITICAL_SECTION recv_cs;    //操作同一个socket连接的读写缓冲区
    sockaddr_in remoteAddr;
    int nAddrlen;
};
3

4.socket_packet.h/socket_packet.cpp

socket流数据封装成packet

enum 
{
    PACKET_LOGIN,
    PACKET_GETXX,
    PACKET_SETXX,
};

#pragma pack (push,1)   /*指定1字节对齐,有些编译器会补齐成4字节对齐,需要指定1字节对                        齐,否则底层缓冲区可能对数据的长度判断出错*/ 
typedef struct {
    unsigned int type;        //packet类型
    unsigned int length;        //整个packet的长度
    unsigned int flag;            //附加的标志
    char data[1];            //数据
}packet_t;
#pragma pack (pop)      /*还原默认字节对齐*/  

class socket_packet
{
public:
    enum
    {
        err_stream_check,
        err_stream_state=-4099,
    };    //在这一层出错时返回的错误标志
    socket_packet(socket_stream *stream);        //构造
    ~socket_packet();            //析构,释放相应内存
    int send_packet(packet_t *packet,int length);        //发送一个packet
    int recv_packet();            //接收一个完整的packet,返回接收的标志
    char *get_buffer();        //接收成功后,用该函数获取packet数据
private:
    bool check_buffer(packet_t *p);    //检查本类中申请的buffer是否足够大,不足将继续申请                                //内存
    socket_stream *mStream;        //封装在该层的底层类
    char *buffer;            //可变长的缓冲区
    int bufLength;            //缓冲区长度
};
4 

5.session_s.h/session_s.cpp

一个session的服务端代码,用来获取用户请求和发送处理结果

class session_s
{
public:
    enum {
        disconected,
        have_request,
    };    //判断session的状态
    session_s(socket_packet *sp);    //构造
    ~session_s();    //析构
    bool login(char *username,char*pass);        
    bool _register(void *p);    
    int wait_request();        //等待用户请求
    request_t *get_request();    //获取用户请求    
    bool send_reply(reply_t *reply);    //发送回复
    void login_success(char* name);    //登录成功后设置相关标志
    bool IsLogin(){return this->b_login;}        //判断当前用户是否已经登录
    void setSqlOperate(Operate * o){op=o;}        //设置数据库操作类
    char* getusername(){return username;}        //登录成功后可用来获取当前用户名
    Operate *op;
private:
    bool b_login;
    char username[128];
    socket_packet *sp;
    request_t request;
    char *reply_buffer;
    char reply_buffer_len;    
};
5 

6.session_c.h/session_c.cpp

一个session的客户端代码,用来生成、发送用户请求,接收处理结果

class session_c
{
public:
    enum {
        disconected=-1,
        have_request=1,
    };    //session状态
    session_c(socket_packet *sp);
    ~session_c();
    bool login(char *params);
    bool _register(char* params);
    struct userStruct getUserInfo(char *params);
    int wait_reply();    //等待服务端回复
    reply_t *get_reply();    //获取回复结果
    bool SendAndCheck(request_t *req);    //发送requeset并检查当前状态,等待回复
    int getState(){return this->state;};    //获取当前session状态
    bool addEvent(char* params);    //添加活动
    vector<StationMessageStruct> getStationMessage();//获取站内信
    bool addMessage(char *params);    //发送消息
    vector<EventStruct> getEvent(char* params);    //出发地,目的地,时间,活动类型获取活动
    bool joinEvent(char * params);        //参加某个活动
    vector<string> getParticipants(char* params);    //获取某个活动的所有参与者
    EventStruct getEventByID(char* params);    //获取某一个活动
    bool updatauserinfo(char* params);    //修改用户信息
     bool exitEvent(char *params);        //退出某个活动
     bool setEventState(char *parmas);    //设置活动的状态,进行中,完成,取消
     vector<EventStruct> getEventByConditions(char* params);//获取已发布或已加入的活动
     bool setSecurity(char* params);    //设置密保
     string getSecurity(char *params);        //获取密保问题
     string checkSecurity(char *params);    //检查密保回答是否正确,返回密码
private:
    int send_request(request_t *req);    //发送请求
    int state;        //当前session状态
    socket_packet *sp;    //封装的packet处理类
    bool b_login;    
    reply_t reply;
    char *buffer;
    int bufferlen;
};
 

7.request_reply.h

以上两个session类中所需的一些定义: 

enum
{
    TYPE_LOGIN,
    TYPE_REGISTER,
    TYPE_GETUSERINFO,
    TYPE_ADDEVENT,
    TYPE_GETMESSAGE,
    TYPE_ADDMESSAGE,
    TYPE_GETEVENT,
    TYPE_JOINEVENT,
    TYPE_GETPARTICIPANTS,
    TYPE_GETEVENTDETAILBYID,
    TYPE_UPDATEUSERINFO,
    TYPE_EXITEVENT,
    TYPE_SETEVENTSTATE,
    TYPE_GETEVENTBYCONDITIONS,
    TYPE_SETSECURITY,
    TYPE_GETSECURITY,
    TYPE_CHECKSECURITY
};
typedef struct{
    int type;
    int flag;
    int datalen;
    char *data;
}request_t;

typedef struct{
    int type;
    int flag;
    int datalen;
    char *data;
}reply_t;
7

8.UserClient.h/UserClient.cpp

提供给客户端界面的接口类

class UserClient
{
public:
    UserClient(char *ip, unsigned short port);    //连接服务端的ip,port
    bool Login(char *name,char* password);    //登录
    bool Register(struct userStruct userInfo);    //注册
    int getState(){return this->state;};            //获取session状态
    bool reConnect();                    //重连
    bool fisrtConnect();                    //第一次连接
    struct userStruct getUserInfo(char* username);    //获取用户信息
    bool addEvent(EventStruct Event);                //发布活动
    bool sendMessage(StationMessageStruct message);    //发送消息
    vector<StationMessageStruct> getStationMessage();    //获取站内信
     vector<EventStruct> getEvent(string StartSite, string EndSite, string StartTime,string EventType);
//获取活动列表
    bool joinEvent(int EventID, string username);            //加入活动
    vector<string> getParticipants(int EventID);            //获取参与者列表
    EventStruct getEventById(int EventID);                //获取活动详情
    void Logout();                                //注销当前用户
    bool UpdateUserInfo(struct userStruct userInfo);        //修改用户信息
     bool ExitEvent(int EventID,string username);        //退出活动
     bool SetEventState(int EventID,int state);            //设置活动状态
     vector<EventStruct> getEventByConditions(string publisher,string participant,int state);
//获取已发布或已加入的活动
     bool SetSecurity(string username,string sercurity,string answer);
//设置密保
     string GetSecurity(string username);
//获取密保问题
     string CheckSecurity(string username,string security,string answer);
//检查密保回答是否正确,如果正确返回密码
//服务端会返回密码
private:
    int state;
    session_c* sc;        //封装的session类
    char mIp[16];
    unsigned short mPort;
    char *buffer;
    int bufferlen;
};
View Code

9.Service.h/Service.cpp

服务端服务代码

class Service
{
public:
    enum{
        failed,
        success,
    };        //当前服务状态
    Service(unsigned short port);    //构造要监听的端口
    ~Service();    //析构
    int get_state(){return state;};        //获取当前服务状态
    void start_loop();                //开始循环,等待连接
    void setSqlOperate(Operate *o){op=o;}    //设置数据库操作类
    Operate *getSqlOperate(){return op;};    //获取数据库操作类
private:
    Operate *op;
    socket_packet *sp;
    int state;
    SOCKET slisten;
    void  new_connect_handler(SOCKET);        //每一个新连接都会生成一个新线程处理
};
View Code

10.serverthread.h

处理每个连接的线程逻辑代码

DWORD WINAPI myServerThread(LPVOID lpParam)
{    /*每一个连接都会有一个这样的处理线程*/
    ServerThreadParam *lp =(ServerThreadParam*)lpParam;
    session_s *s = lp->session;
    while(1)
    {
        int state = s->wait_request();
        if (state == s->disconected)
            break;
        request_t * req = s->get_request();    //获取请求
//根据不同的请求类型,调用不同的处理逻辑(service_xxx)。
        switch(req->type)
        {
        case (TYPE_LOGIN):
            {
                service_login(s,req);
                break;
            }
        case(TYPE_REGISTER):
            {
                service_register(s,req);
                break;
            }
        case(TYPE_GETUSERINFO):
            {
                service_getuserinfo(s,req);
                break;
            }
        case(TYPE_ADDEVENT):
            {
                service_addevent(s,req);
                break;
            }
        case(TYPE_GETMESSAGE):
            {    
                service_getmessages(s,req);
                break;
            }
        case(TYPE_ADDMESSAGE):
            {
                service_addmessage(s,req);
                break;
            }
        case(TYPE_GETEVENT):
            {
                service_getevent(s,req);
                break;
            }
        case(TYPE_JOINEVENT):
        {
            service_joinevent(s,req);
            break;
        }
        case(TYPE_GETPARTICIPANTS):
        {
            service_getparticipants(s,req);
            break;
        }
        case(TYPE_GETEVENTDETAILBYID):
            {
                service_geteventdetail(s,req);
                break;
            }
        case(TYPE_UPDATEUSERINFO):
            {
                service_updateuserinfo(s,req);
                break;
            }
        case(TYPE_EXITEVENT):
            {
                service_exitevent(s,req);
                break;
            }
        case(TYPE_SETEVENTSTATE):
            {
                service_seteventstate(s,req);
                break;
            }
        case(TYPE_GETEVENTBYCONDITIONS):
            {
                service_geteventbycondition(s,req);
                break;
            }
        case(TYPE_SETSECURITY):
            {
                service_setsecurity(s,req);
                break;
            }
        default:
            break;
        }
    }
    return 0;
}
View Code

5 运行说明

  https://pan.baidu.com/s/1eSnfZIM

原文地址:https://www.cnblogs.com/shuangshuangblog/p/7794576.html