📄 connectinfo.cpp
字号:
/*******************************************************
连接类实现代码
主要纪录了与连接相关的操作和信息,
当进入一个连接后,就创建一个这样的对象,来管理本次连接
当接收到数据时调用handleRecvPacket()进行解密和根据OPCODE
功能重定向到相关功能处理函数,在各功能函数中进行处理。
作者:颜永华
********************************************************/
#include "StdAfx.h"
#include "DB.h"
#include ".\connectinfo.h"
#include "BlowFish.h"
/*
初始化密钥
*/
CConnectInfo::CConnectInfo(void)
{
this->FirstFillinKey(Key.SendKey);
this->FirstFillinKey(Key.RecvKey);
this->keyNum=0; //纪录发送key的次数
}
/*填充密钥函数
*/
void CConnectInfo::FirstFillinKey(BYTE *key)
{
for(int i = 0; i < 8; i++)
key[i] = (BYTE)rand();
}
CConnectInfo::~CConnectInfo(void)
{
closesocket(sock);
}
/*投递接收请求
1)postRecv()功能
为缓冲区投递接收请求,
在投递接收请求时,调用
2)参数LPOVERLAPPEDEX pOverlappedEx
扩展OVERLAPPEDEX结构
以更好的记录数据
typedef struct OverlappedEX
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
int nOvFlag;//重叠类型
}OVERLAPPEDEX,*LPOVERLAPPEDEX;
*/
void CConnectInfo::postRecv(LPOVERLAPPEDEX pOverlappedEx)
{
pOverlappedEx->nOvFlag=RECV;
DWORD numberBytesRecv,flag=0;
int ret;
ret=::WSARecv(sock,&pOverlappedEx->DataBuf,1,&numberBytesRecv,&flag,&pOverlappedEx->Overlapped,NULL);
if(ret==SOCKET_ERROR)
{if(WSA_IO_PENDING!=WSAGetLastError())
MessageBox(NULL,"postRecv is err","err",0);
}
}
/*
添加连接对象到连表
参数LPOVERLAPPEDEX pOverlappedEx
扩展OVERLAPPEDEX结构
以更好的记录数据
typedef struct OverlappedEX
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
int nOvFlag;//重叠类型
}OVERLAPPEDEX,*LPOVERLAPPEDEX;
*/
void CConnectInfo::AddToList(LPOVERLAPPEDEX pOverlappedEx)
{
//加入到链表
OlList.InsertAfter(OlList.GetHeadPosition(),pOverlappedEx);
//BuffList.InsertAfter(BuffList.GetHeadPosition(),pOverlappedEx->DataBuf.buf );
}
/*删除连表中所有连接对象*/
void CConnectInfo::DelAllFromList()
{
POSITION pos=OlList.GetHeadPosition();
LPOVERLAPPEDEX pOverlappedEx=NULL;//char *pBuff=NULL;
while(pos!=NULL)
{
pOverlappedEx=OlList.GetNext(pos);
//OlList.RemoveAt(pos);
::GlobalFree(pOverlappedEx->DataBuf.buf);
::GlobalFree(pOverlappedEx);
}
}
/*
1)AllocRecvBuff()为接收数据分配缓冲区
2)参数len为要分配的字节数
*/
LPOVERLAPPEDEX CConnectInfo::AllocRecvBuff(int len)
{
LPOVERLAPPEDEX pOverlappedEx=(LPOVERLAPPEDEX)::GlobalAlloc(GPTR,sizeof(OVERLAPPEDEX));
pOverlappedEx->DataBuf.buf =(char*)::GlobalAlloc(GPTR,(sizeof(char)*len));
pOverlappedEx->DataBuf.len=len;
//AddToList(pOverlappedEx);
return pOverlappedEx;
}
/*
1)AllocSendBuff()为发送数据分配缓冲区
2)const char packet[]待发送数据的缓冲区地址
3)待发送数据的字节数
*/
LPOVERLAPPEDEX CConnectInfo::AllocSendBuff(const char packet[],int len)
{
LPOVERLAPPEDEX pOverlappedEx=(LPOVERLAPPEDEX)::GlobalAlloc(GPTR,sizeof(OVERLAPPEDEX));
pOverlappedEx->DataBuf.buf =(char*)::GlobalAlloc(GPTR,(sizeof(char)*len));
pOverlappedEx->DataBuf.len=len;
memcpy(pOverlappedEx->DataBuf.buf,packet,len);
//AddToList(pOverlappedEx);
return pOverlappedEx;
}
/*
1)postSend()投递发送请求
2)参数LPOVERLAPPEDEX pOverlappedEx
扩展OVERLAPPEDEX结构
以更好的记录数据
typedef struct OverlappedEX
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
int nOvFlag;//重叠类型
}OVERLAPPEDEX,*LPOVERLAPPEDEX;
*/
void CConnectInfo::postSend(LPOVERLAPPEDEX pOverlappedEx)
{
pOverlappedEx->nOvFlag=SEND;
DWORD numberBytesRecv,flag=1;
int ret;
ret=::WSASend(sock,&pOverlappedEx->DataBuf,1,&numberBytesRecv,flag,&pOverlappedEx->Overlapped,NULL);
if(ret==SOCKET_ERROR)
{if(WSA_IO_PENDING!=WSAGetLastError())
MessageBox(NULL,"post send is err","err",0);
}
}
/*给客户端//发送KEY KEY的长度是8*/
void CConnectInfo::sendKey(BYTE *Key)
{
//发送KEY KEY的长度是8
EnCodeKey(Key);
postSend(AllocSendBuff((char*)Key,9));
DeCodeKey(Key);
if(this->keyNum==0)
{ this->keyNum++;
//为登陆封包投递接收
postRecv(AllocRecvBuff(DATA_BUFSIZE));
}
}
/*
1)handleLoginPacket()用来处理用户登陆的封包
2)参数pPack解密后的数据首地址
3)参数LPOVERLAPPEDEX pOverlappedEx
扩展OVERLAPPEDEX结构
以更好的记录数据
typedef struct OverlappedEX
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
int nOvFlag;//重叠类型
}OVERLAPPEDEX,*LPOVERLAPPEDEX;
4)参数len是接解密数据的长度
*/
void CConnectInfo::handleLoginPacket(BYTE *pPack,LPOVERLAPPEDEX pOlEx,int len)
{//登陆
//转换缓冲区数据为LOGIN_PACKET类型
LPLOGIN_PACKET lPack=(LPLOGIN_PACKET)pPack;
//打包返回标志包
RETFLAG retFlag;
memset(&retFlag,0,sizeof(RETFLAG));
retFlag.wCode=SERVER_LOGIN;
retFlag.wLen=sizeof(RETFLAG);
//声明一个数据库对象,用完直接释放
CDB db;
int ret=db.Login(lPack->customerName,lPack->customerPwd,lPack->customer_login_ip);
switch(ret)
{
case -1:
{//封包银行错误
retFlag.bFlag=FLAG_NOBANK;
}break;
case 0:
{//操作失败
retFlag.bFlag=FLAG_FAILED;
}break;
case 1:
{//成功
retFlag.bFlag=FLAG_SUCCEED;
}break;
}
//发送操作结果
postSend(AllocSendBuff((CHAR*)&retFlag,sizeof(RETFLAG)));
//为下一次接收做准备
postRecv(pOlEx);
}
/*
1)exitsys()处理系统下线封包
2)参数pPack解密后的数据首地址
3)参数LPOVERLAPPEDEX pOverlappedEx
扩展OVERLAPPEDEX结构
以更好的记录数据
typedef struct OverlappedEX
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
int nOvFlag;//重叠类型
}OVERLAPPEDEX,*LPOVERLAPPEDEX;
4)参数len是接解密数据的长度
*/
void CConnectInfo::exitsys(BYTE *pPack,LPOVERLAPPEDEX pOl,int len)
{//下线
//转换接收缓冲区数据为EXIT_PACKET类型
LPEXIT_PACKET lPack=(LPEXIT_PACKET)pPack;
CDB db;
db.DownLine(lPack->customerName);
}
/*
1)handleRegPacket()处理注册封包
2)参数pPack解密后的数据首地址
3)参数LPOVERLAPPEDEX pOverlappedEx
扩展OVERLAPPEDEX结构
以更好的记录数据
typedef struct OverlappedEX
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
int nOvFlag;//重叠类型
}OVERLAPPEDEX,*LPOVERLAPPEDEX;
4)参数len是接解密数据的长度
*/
void CConnectInfo::handleRegPacket(BYTE *pPack,LPOVERLAPPEDEX pOl,int len)
{//处理注册封包
//转换
LPFIRST_REG_PACKET lPack=(LPFIRST_REG_PACKET)pPack;
strcpy(lPack->customerRegBankIP,inet_ntoa(netaddr.sin_addr));
//打包返回状态标志
RETFLAG retFlag;
memset(&retFlag,0,sizeof(RETFLAG));
retFlag.wCode=SERVER_FIRST_REG;
retFlag.wLen=sizeof(RETFLAG);
//向数据库写入数据
CDB db;
int ret=db.firstReg(lPack->customerName,lPack->customerPwd,
lPack->accountId,lPack->accountPwd,lPack->customerRealName,
lPack->customerRegBankIP,lPack->customerPhone,lPack->customerAddr,lPack->customerEmail);
switch(ret)
{
case 1:
{//操作成功
retFlag.bFlag=FLAG_SUCCEED;
}break;
case -1:
{//没有银行
retFlag.bFlag=FLAG_NOBANK;
}break;
case -2:
{//用户已经存在
retFlag.bFlag=FLAG_YESUSER;
}break;
case -4:
{//账号已经被注册
retFlag.bFlag=FLAG_YESACC;
}break;
case 0:
default:
{//操作失败
retFlag.bFlag=FLAG_FAILED;
};
}
//发送数据
postSend(AllocSendBuff((CHAR*)&retFlag,sizeof(RETFLAG)));
//为下次接收提供缓冲区
postRecv(pOl);
}
/*
1)handleShowUserInfo()处理显示请求
2)参数pPack解密后的数据首地址
3)参数LPOVERLAPPEDEX pOverlappedEx
扩展OVERLAPPEDEX结构
以更好的记录数据
typedef struct OverlappedEX
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
int nOvFlag;//重叠类型
}OVERLAPPEDEX,*LPOVERLAPPEDEX;
4)参数len是接解密数据的长度
5)返回用户的相关信息
*/
void CConnectInfo::handleShowUserInfo(BYTE *pPack,LPOVERLAPPEDEX pOl,int len)
{////处理显示请求
LPREQSHOW_PACKET lPack=(LPREQSHOW_PACKET)pPack;
//打包显示封包
SHOW_INFO_PACKET showPacket;
memset(&showPacket,0,sizeof(SHOW_INFO_PACKET));
showPacket.wCode=SERVER_SHOW_INFO;
showPacket.wLen=sizeof(SHOW_INFO_PACKET);
//从数据库中获得显示信息
CDB db;
db.ShowCustomerInfo(lPack->customerName,&showPacket);
postSend(AllocSendBuff((CHAR*)&showPacket,sizeof(SHOW_INFO_PACKET)));
this->postRecv(pOl);
}
/*
1)handleRecvPacket()本函数是整个的关键,他主要用来,
对接受到的数据进行,解密本通过
OPCODE来判断,下一不的具体操作应该转向什么地方
2)参数LPOVERLAPPEDEX pOverlappedEx
扩展OVERLAPPEDEX结构
以更好的记录数据
typedef struct OverlappedEX
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
int nOvFlag;//重叠类型
}OVERLAPPEDEX,*LPOVERLAPPEDEX;
3)参数len是接收原始封包数据的长度
*/
int CConnectInfo::handleRecvPacket(LPOVERLAPPEDEX pOl,int len)
{
//解密接收到的数据
BYTE *pPack=(BYTE*)malloc(sizeof(BYTE)*(len-9));
DeCodeFlow(Key.RecvKey,Key.RecvKey,pPack,(BYTE*)pOl->DataBuf.buf,len-9);
switch(_OPCODE(pPack))
{
case CLIENT_LOGIN://登陆
handleLoginPacket(pPack,pOl,len-9);
break;
case CLIENT_SHOW_INFO://显示请求
handleShowUserInfo(pPack,pOl,len-9);
break;
case CLIENT_FIRST_REG://注册
handleRegPacket(pPack,pOl,len-9);
break;
case CLIENT_INMONEY://存款
handleIncomePacket(pPack,pOl,len-9);
break;
case CLIENT_OUTMONEY://取款
handlePayoutPacket(pPack,pOl,len-9);
break;
case CLIENT_TRANSFER://转帐
handleTransferPacket(pPack,pOl,len-9);
break;
case CLIENT_FIND_REQ://查询余额
handleFindBalance(pPack,pOl,len-9);
break;
case CLIENT_NOTIFY_PASSWORD://修改密码
handleNotifyPassword(pPack,pOl,len-9);
break;
case CLIENT_EXIT://客户退出
exitsys(pPack,pOl,len-9);
break;
default:
free(pPack);
return 0;
}
free(pPack);
return 1;
}
/*
1)handleNotifyPassword修改密码
2)参数pPack解密后的数据首地址
3)参数LPOVERLAPPEDEX pOverlappedEx
扩展OVERLAPPEDEX结构
以更好的记录数据
typedef struct OverlappedEX
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
int nOvFlag;//重叠类型
}OVERLAPPEDEX,*LPOVERLAPPEDEX;
4)参数len是接解密数据的长度
*/
void CConnectInfo::handleNotifyPassword(BYTE *pPack,LPOVERLAPPEDEX pOl,int len)
{
//转换封包为NOTIFY_PASSWORD_PACKET类型
LPNOTIFY_PASSWORD_PACKET lPack=(LPNOTIFY_PASSWORD_PACKET)pPack;
//打包返回标志
RETFLAG retFlag;
memset(&retFlag,0,sizeof(RETFLAG));
retFlag.wCode=SERVER_NOTIFY_PASSWORD;
retFlag.wLen=sizeof(RETFLAG);
//更改数据库中密码
CDB db;
if(db.notifyPassword(lPack->accountId,lPack->accountOldPwd,lPack->accountNewPwd))
{
retFlag.bFlag=FLAG_SUCCEED;
}else
retFlag.bFlag=FLAG_FAILED;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -