已阅读5页,还剩36页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
重 庆 理 工 大 学课程设计课程 面向对象程序设计I 题目 基于WinSock的局域 网通信系统的开发 院系名称 计算机科学与工程学院 班 级 l 学生姓名 l 学号 l 指导教师 l 评阅教师 l 时 间 2012年5月28日-6月1日 重庆理工大学课程设计 1 系统分析1.1 功能模块分析1.1.1 模块一消息实体类的实现: 主要用来封装和存储在网络上传送消息(消息块),除此之外还主要负责管理消息块。它主要记录的信息包括:消息源地址、消息源端口、消息长度、消息头、消息块(消息数据区)、和游标()由于记录读写消息块时的位置;该类主要提供的操作包括:读写消息头操作、读写一个字节数据操作、读写两个字节数据操作、读写四个字节数据操作、读写指定字节的数据操作、提供消息块地址操作、游标操作、消息头操作。在线用户信息类的实现: 主要工作为记录和管理当前在线的所有用户,其中在线用户的信息包括:用户号、外网地址、端口号、在线状态和密码;同时该类需要提供的操作包括:赋值操作、判断两个用户是否相同的操作、更新用户在线信息的操作。系统的总体结构示意图:数据库主函数: 流程图: 服务器 客户端 客户端服务器程序启动读取配置文件成功?是否成功?连接数据库是否是否成功?初始化socket通信 启动接收消息线程启动发送消息线程H?V?输出版本信息输入版本信息是是是输入状态信息S?启动处理消息线程Q?主线程接收键盘输入工作线程退出,主线程退出是是1.1.2 模块二数据库用户用户数据库应用系统标准接口数据库管理系统数据库用户管理类的设计(完善服务器消息处理线程)完善服务器消息处理线程中的用户管理类的设计,用户管理类包括用户当前的状态、查询用户的在线信息、设置用户的状态、新增在线的用户、删除在线用户、判断一个用户是否在线、统计在线人数、随机返回在线人数4重庆理工大学课程设计 2 系统实现2.1模块一实例系统开发前的准备:/定义公共头文件#ifndef GLOBAL_DEFINE_H/为了防止重复定义而添加的宏#define GLOBAL_DEFINE_H/为了防止重复定义而添加的宏/包含一些通用的头文件#include /为了使用sring类#include /标准C+输入输出#include #include using namespace std;/引入标准C+命名空间#define MAX_STRING_LEN 512/最大的字符串长度#define DB_SQL_ERROR0/SQL语句执行错误#define DB_SQL_SUCCESS1/SQL语句正确执行#define DB_SQL_NO_DATA_FOUND2/没有找到数据#define MAX_MSG_QUEUE_NUM1000/消息队列最大存放消息数#define SERVER_ID10000/服务器主动发出的消息头中的id号#endif /GLOBAL_DEFINE_H,为了防止重复定义而添加的宏/定义协议#ifndef IM_PROTOCOL_H#define IM_PROTOCOL_H/常量定义const unsigned int SYSTEM_UID = 10000;/系统主动发送的包里面的uid const unsigned short MAX_PACKET_LEN = 3000;/最大包的长度const unsigned short MAX_TEXT_LEN = 1500;/最大聊天长度const unsigned short MAX_CONTACT_NUM = 512;/最大的好友数 const unsigned char MAX_NICK_LEN = 16;/最大别名长度const unsigned char MAX_EMAIL_LEN = 32;/最大EMAIL长度const unsigned char MAX_NAME_LEN = 16;/最大NAME长度const unsigned char MAX_COLLEGE_LEN = 20;/最大学校长度const unsigned char MAX_PROFESSION_LEN = 64;/最大专业长度const unsigned char MAX_NOTE_LEN = 128;/最大个性说明长度const unsigned char MAX_TEL_LEN = 12;/最大电话号码长度const unsigned char MAX_PASSWORD_LEN = 16;/最大密码长度const unsigned char MAX_SEND_CONTACT_NUM = 8;/每次发送的最大联系人个数,查找好友时用 const unsigned char TIME_LEN = 18;/时间占用的字节数/基本数据结构定义/改变字节对齐方式,在网络上传输的结构,必须使用字节对齐#pragma pack(1) struct IM_Header/定义数据包包头unsigned short cmd;/本条消息类型unsigned int id;/发送这条消息的用户号unsigned int seq;/消息号unsigned int reserved;/保留字节;struct usr_info_base/用户信息unsigned intuser_id;/用户IDunsigned charpasswordMAX_PASSWORD_LEN+1;/密码unsigned charnickMAX_NICK_LEN+1;/昵称unsigned shortpicture;/头像的索引号unsigned charnameMAX_NAME_LEN+1;/姓名unsigned chargengder;/性别 男=0,女=1unsigned charage;/年龄unsigned charemailMAX_EMAIL_LEN+1;/邮件unsigned chartelephoneMAX_TEL_LEN+1;/电话unsigned charcollegeMAX_COLLEGE_LEN+1;/毕业院校unsigned charprofessionMAX_PROFESSION_LEN+1;/专业unsigned charnoteMAX_NOTE_LEN+1;/个性说明;struct usr_info_online/在线用户信息unsigned intuser_id;/用户IDunsigned intIP;/外网IPunsigned shortim_udp_port;/外网端口unsigned char status;/状态等级 在线=0,隐身=1,离开=2,离线=3;#pragma pack()struct IM_server_info/服务器信息unsigned intip;/服务器ipunsigned shortport;/服务器端口unsigned intuser_online;/在线用户数量;/协议定义enum IM_CMD/定义协议命令码/帐号管理IM_ACCOUNT_REGISTER=0x1000,/注册CS,0x1000IM_ACCOUNT_SET_INFO,/更新信息C-S,0x1001/会话管理IM_SESSION_LOGIN,/登录CS,0x1002IM_SESSION_STATUS_CHANGE,/状态改变CS,0x1003IM_SESSION_HEARTBEAT,/心跳CS,0x1004IM_SESSION_LOGOUT,/退出C-S,0x1005/联系人管理IM_CONTACT_SEARCH,/查找CS,0x1006IM_CONTACT_ADD,/添加CS,0x1007IM_CONTACT_DEL,/删除C-S,0x1008IM_CONTACT_GET_LIST,/取列表CS,0x1009IM_GET_ONLINE_INFO,/取在线信息CS,0x100A/简单聊天IM_SCHAT_MSG,/文本聊天CC,0x100B;/添加联系人子命令#defineIM_CONTACT_ADD_REQ0x00/请求C1S#defineIM_CONTACT_ADD_NOTIFY0x01/通知SC2/用户会话状态#defineIM_STATUS_ONLINE0x00/用户在线#defineIM_STATUS_HIDE0x01/用户隐身#defineIM_STATUS_OUTWAY0x02/用户离开#defineIM_STATUS_OFFLINE0x03/用户离线/联系人查找类型#defineIM_SEARCH_ID0x00/根据号码查找联系人#defineIM_SEARCH_NICK0x01/根据昵称查找联系人#defineIM_SEARCH_RANDOM0x02/查找在线用户/注册错误码#defineIM_REGISTER_SUCESS0x00/注册成功#defineIM_REGISTER_ERROR0x01/注册失败#defineIM_REGISTER_ERROR_DB0x02/注册失败,数据库错误/更新信息错误码#defineIM_SET_INFO_SUCCESS0x00/更新跟人信息成功#defineIM_SET_INFO_ERROR0x01/更新个人信息失败#defineIM_SET_INFO_ERROR_DB0x02/更新个人信息失败,数据库错误/登陆错误码#defineIM_LOGIN_SUCCESS0x00/登录成功#defineIM_LOGIN_ERROR_PSW0x01/登录失败,密码错误#defineIM_LOGIN_ERROR_UID_UNVALID0x02/用户ID无效#defineIM_LOGIN_ERROR_DB0x03/数据库错误/增加联系人错误码#defineIM_CONTACT_ADD_SUCCESS0x00/添加联系人成功#defineIM_CONTACT_ADD_ERROR0x01/添加联系人失败/删除联系人错误码#defineIM_CONTACT_DEL_SUCCESS0x00/删除联系人成功#defineIM_CONTACT_DEL_ERROR0x01/删除联系人失败#endif/IM_PROTOCOL_H消息实体类的实现:#ifndef IM_MESSAGE_BLOCK_H /避免重复定义#define IM_MESSAGE_BLOCK_H#include IM_Protocol.h#include class IM_Message_Blockpublic:IM_Message_Block():src_ip_(0),src_port_(0),length_(0),cursor_(0),header_(IM_Header*)data_) /消息头的地址就是整个数据包中数据块的首地址IM_Message_Block(void)public:IM_Header* get_header() /获取消息头指针return header_;void set_header(const IM_Header* header) /设置消息头memcpy(char*)header_,header,sizeof(IM_Header); /内存拷贝unsigned char* get_data() /获取数据块首地址return data_;unsigned short get_cursor() /获取光标return cursor_;void read_header(IM_Header& header) /读取header.cmd=ntohs(header_-cmd);header.id=ntohl(header_-id);header.seq=ntohl(header_-seq);header.reserved=ntohl(header_-reserved);cursor_+=sizeof(IM_Header);void read_UINT8(unsigned char* value)*value = *(data_+cursor_);cursor_+;void read_UINT16(unsigned short* value)*value = ntohs(*(unsigned short*)(data_+cursor_);cursor_+=2;void read_UINT32(unsigned int* value)*value = ntohl(*(unsigned int*)(data_+cursor_);cursor_+=4;void read_buffer(char* value,int length)memcpy(char*)value,(char*)data_+cursor_,length);cursor_+=length;void write_header(const IM_Header& header)header_-cmd=htons(header.cmd);header_-id=htonl(header.id);header_-seq=htonl(header.seq);header_-reserved=htonl(header.reserved);cursor_+=sizeof(IM_Header);void write_UINT8(unsigned char value)*(data_+cursor_)=value;cursor_+;void write_UINT16(unsigned short value)*(unsigned short*)(data_+cursor_)=htons(value);cursor_+=2;void write_UINT32(unsigned int value)*(unsigned int*)(data_+cursor_)=htonl(value);cursor_+=4;void write_buffer(const char* value,int length)memcpy(char*)data_+cursor_,value,length);cursor_+=length;void skip(int length)cursor_+=length;void back(int length)cursor_-=length;void set_cursor(unsigned short cursor)cursor_=cursor;public:/以下三个变量外部需要访问unsigned intsrc_ip_;unsigned shortsrc_port_;unsigned intlength_;private:unsigned chardata_MAX_PACKET_LEN;IM_Header*header_;unsigned shortcursor_;#endif/IM_MESSAGE_BLOCK_H在线用户信息类的实现:/定义IM_User_Block类的头文件#ifndef IM_USER_BLOCK_H#define IM_USER_BLOCK_H#include IM_Protocol.hclass IM_User_Blockpublic:IM_User_Block(const unsigned int& uid=0,const unsigned int& ip=0,const unsigned short& port=0,const unsigned char& status=0,const unsigned char* pwd=0);IM_User_Block& operator=(const IM_User_Block& ublk);/拷贝构造函数bool operator=(const IM_User_Block& ublk)const;/重载=运算符,判断两个用户id是否一致void Update_Info(const IM_User_Block& ublk);/更新用户信息unsigned int_uid;/IDunsigned int_ip;/IPunsigned short_port;/im外网udp端口unsigned char_status;/在线状态在线=0,隐身=1,离开=2,离线=3unsigned char_pwdMAX_PASSWORD_LEN+1;/password;#endif/IM_USER_BLOCK_H/新建IM_User_Block的源文件#include Global_Define.h#include IM_User_Block.hIM_User_Block:IM_User_Block(const unsigned int& uid,const unsigned int& ip,const unsigned short& port,const unsigned char& status,const unsigned char* pwd):_uid(uid),_ip(ip),_port(port),_status(status)if(pwd)strcpy(char*)_pwd,(char*)pwd);_pwdMAX_PASSWORD_LEN = 0;elsememset(_pwd,0,MAX_PASSWORD_LEN+1);IM_User_Block& IM_User_Block:operator=(const IM_User_Block& ublk)this-_uid = ublk._uid;this-_ip = ublk._ip;this-_port = ublk._port;this-_status = ublk._status;strcpy(char*)this-_pwd,(char*)ublk._pwd);return *this;bool IM_User_Block:operator=(const IM_User_Block& ublk)constreturn this-_uid = ublk._uid;void IM_User_Block:Update_Info(const IM_User_Block& ublk)if(this-_uid = ublk._uid)this-_ip = ublk._ip;this-_port = ublk._port;this-_status = ublk._status;strcpy(char*)this-_pwd,(char*)ublk._pwd);实例系统输入/输出类的实现:/服务器配置文件信息im_appserverdb_ip =127.0.0.1db_port = 3306db_name = P2PServerDBdb_usr = myiddb_pwd = myidim_server_udp_port = 5402recv_producer_num = 1send_consumer_num = 1process_consumer_num = 2/输入/输出类的实现#ifndef IM_CONFIG_PARSER_H#define IM_CONFIG_PARSER_H#include Global_Define.h#include class IM_Config_Parserpublic:IM_Config_Parser(const char* file_name);virtual IM_Config_Parser(void);public:bool open();/根据信息类型strType和键strKey获取键值strValuebool get_string(const char* strType, const char* strKey, char* strValue,const int& nMaxLen);/根据信息类型strType和键strKey更新键值bool update_string(const char* strType, const char* strKey, const char* strValue);private:string _file_name;/文件名称fstream _file;/文件流对象;#endif/IM_CONFIG_PARSER_H#include IM_Config_Parser.hIM_Config_Parser:IM_Config_Parser(const char* file_name):_file_name(string(file_name)IM_Config_Parser:IM_Config_Parser(void)_file.close();bool IM_Config_Parser:open()_file.open(_file_name.c_str(),ios:in|ios:out);/通过成员函数c_str()把string对象转换成c中的字符串样式if(!_file)return false;return true;bool IM_Config_Parser:get_string(const char* strType, const char* strKey, char* strValue,const int& nMaxLen)if(!_file)return false;_file.seekg(0,ios:beg);/从文件头开始查找char c = _file.get();if(c = )string strReadType;/获取信息类型关键字for(; ;)strReadType = ;while(c=_file.get()!= ) & (c)if(c != )/空格不算strReadType += c;if(!c)return false;if(c = )if(strReadType = string(strType)while(c=_file.get()!= n) & (c);if(!c)return false;break;elsewhile(c=_file.get()!= n) & (c);if(!c)return false;while(c=_file.get()!= ) & (c);if(!c)return false;/获取信息关键字for(; ;)strReadType = ;while(c=_file.get()!= =) & (c) & (c!=n)if(c != )/空格不算strReadType += c;if(!c)return false;if(c = n)strReadType = ;continue;if(c = =)if(strReadType = string(strKey)break;elsewhile(c=_file.get()!= n) & (c);if(!c)return false;elsestrReadType = ;continue;/获取键值string strReadValue;while(c=_file.get()!= n) & (c) & (c!=/)/去掉注释if(c != )/空格不算strReadValue += c;if(strReadValue.size() nMaxLen)return false;strcpy(strValue,strReadValue.c_str();strValuestrReadValue.size() = 0;return true;elsereturn false;bool IM_Config_Parser:update_string(const char *strType, const char *strKey, const char *strValue)if(!_file)return false;_file.seekg(0,ios:beg);/从文件头开始查找string strFileContent;char c = _file.get();while(!_file.eof()/先把文件的所有内容读取出来strFileContent += c;_file.get(c);/准备替换int nTypeIndex = -1;int nKeyIndex = -1;int nValueStartIndex = -1;int nValueEndIndex = -1;nTypeIndex = strFileContent.find(strType);if(nTypeIndex = -1)return false;nKeyIndex = strFileContent.find(strKey,nTypeIndex);if(nKeyIndex = -1)return false;nValueStartIndex = strFileContent.find(=,nKeyIndex);if(nValueStartIndex = -1)return false;nValueEndIndex = strFileContent.find(n,nValueStartIndex);if(nValueEndIndex = -1)return false;/*用新值替换原来的值,replace的第一个参数表示从哪里开始替换,第二个参数表示替换多少个字符,第三个参数表示需要拿去替换的新值*/strFileContent.replace(nValueStartIndex+1,nValueEndIndex-nValueStartIndex-1,strValue);/然后再将替换后的信息重新写到文件中去_file.clear();/清除原有的错误标志_file.close();/重新打开文件,为后面的写入新内容做准备_file.open(_file_name.c_str(),ios:out);if(!_file)return false;const char *strTemp = strFileContent.c_str();int i = 0;while(strTempi!=0)_file.put(strTempi+);_file.clear();_file.close();_file.open(_file_name.c_str(),ios:in|ios:out);if(!_file)return false;return true;主函数:#include Global_Define.h#include IM_Protocol.h#include Message_Queue.h#include IM_Message_Block.h#include Udp_Daemon.h#include Account_DB_Access.h#include User_Manager.h#include IM_Config_Parser.h#include Recv_Producer.h#include Send_Consumer.h#include Process_Consumer.h/全局接收消息队列Message_Queue g_rcv_msg_queue;/全局发送消息队列Message_Queue g_send_msg_queue;Udp_Daemon g_udp_daemon; /全局udp通信对象Account_DB_Access g_account_db; /全局数据库操作对象User_Manager g_user_manager; /全局在线用户管理对象int main()/从配置文件读取配置信息IM_Config_Parser fileobj(imserver.ini);if(!fileobj.open()coutopen file:imserver.ini failed.endl;return 0;char db_nameMAX_STRING_LEN = 0;/char server_ipMAX_STRING_LEN = 0;int im_udp_port = 0;int recv_producer_num = 0;int send_consumer_num = 0;int process_consumer_num = 0;char strValueMAX_STRING_LEN;if(fileobj.get_string(im_appserver,db_name,strValue,MAX_STRING_LEN)coutdb_name=strValueendl;strcpy(db_name,strValue);/数据库名称/if(fileobj.get_string(im_appserver,im_ip,strValue,MAX_STRING_LEN)/coutim_ip=strValueendl;/strcpy(server_ip,strValue);/服务器ip/if(fileobj.get_string(im_appserver,im_server_udp_port,strValue,MAX_STRING_LEN)coutim_udp_port=strValueendl;im_udp_port = atoi(strValue);/服务器端口号if(fileobj.get_string(im_appserver,recv_producer_num,strValue,MAX_STRING_LEN)coutrecv_producer_num=strValueendl;recv_producer_num = atoi(strValue);/接收消息线程数if(fileobj.get_string(im_appserver,send_consumer_num,strValue,MAX_STRING_LEN)coutsend_consumer_num=strValueendl;send_consumer_num = atoi(strValue);/发送消息线程数if(fileobj.get_string(im_appserver,process_consumer_num,strValue,MAX_STRING_LEN)coutprocess_consumer_num=strValueendl;process_consumer_num = atoi(strValue);/处理消息线程数/连接数据库if(g_account_db.connect(string(db_name) = false)return 0;/初始化socket通信if(g_udp_daemon.init(im_udp_port) = 0)return 0;Recv_Producer recv_producer(recv_producer_num);/接收消息线程对象Send_Consumer send_consumer(send_consumer_num);/发送消息线程对象Process_Consumer process_consumer(process_consumer_num);/处理消息线程对象recv_producer.start();/启动接收消息线程send_consumer.start();/启动发送消息线程process_consumer.start();/启动处理消息线程cout服务器已经启动.endl;char cmd;/主线程进入无限循环运作for(; ;)cmd = getchar();if(cmd = V | cmd = v)/输出版权信息cout版权所有:重庆理工大学计算机学院计算机科学与技术系endl;cout2010年2月endl;else if(cmd=S | cmd=s)/输出当前服务器状态g_udp_daemon.status();recv_producer.status();send_consumer.status();process_consumer.status();g_user_manager.status();else if(cmd=H | cmd=h)/输出帮助信息coutH|h : helpendl;coutQ|q : exitendl;coutS|s : statusendl;coutV|v : versionrecv_producer-send_comsumer-process_consumerg_udp_daemon.fini();break;Sleep(2000);/主线程等待两秒让其它线程退出cout主线程退出。endl;return 1;2.2模块二实例系统数据库操作类的设计:/引入一个名为Account_DB的类作为基础类#ifndef ACCOUNT_DB_H#define ACCOUNT_DB_H#include Global_Define.h#include IM_Protocol.hclass Account_DBprotected:Account_DB(const string& db_name=, const string& user=, const string& passwd=, const string& host=, const int& port=0):_db_name(db_name), _user(user), _passwd(passwd),_host(host), _port(port)public:virtual Account_DB(void)public:virtual bool connect(const string& db_name=) = 0;/连接数据库virtual bool disconnect() = 0;/断开数据库连接virtual int IsUserExist(const int& uid) = 0;/判断某一用户是否已经注册/检查用户密码是否正确virtual int check_usr_pwd(const usr_info_base& account)=0;/更新用户基本信息virtual int update_usr_base_info(const usr_info_base& account)=0;/查询用户基本信息virtual int query_usr_base_info(usr_info_base& account)=0;/新增用户vi
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 起毛挡车工风险评估与管理考核试卷含答案
- 石脑油预处理装置操作工成果转化能力考核试卷含答案
- 生活燃煤供应工诚信道德强化考核试卷含答案
- 重冶萃取工岗后评优考核试卷含答案
- 水力发电运行值班员安全理论水平考核试卷含答案
- 焊丝镀铜工班组考核水平考核试卷含答案
- 养蜂员岗中流程优化考核试卷含答案
- 具身智能+城市交通智能调度机器人优化方案分析方案
- 单位短视频运营方案
- 无菌灌装技术改造分析方案
- 2017-2026上海十年高考数学专项汇编:专题02 不等式(学生版)
- 2026年先进专用芯片系统封装模组制造项目市场调研报告
- 2026年软件正版化工作实施方案
- 健身房投资入股协议书样本
- GB/T 45939-2025光伏组件封装用共挤胶膜
- NBT 11127-2023 在用钢丝绳芯输送带报废检测技术规范
- 母婴同室院感管理课件
- 农村初中生大五人格与生命意义感的内在关联探究
- 基层治保会培训课件
- 2025至2030年中国杭州房地产行业市场竞争现状及未来趋势研判报告
- TD/T 1024-2010县级土地利用总体规划编制规程
评论
0/150
提交评论