www.pudn.com > Five_QT_by_CT.rar > HallMaster.cpp
#include "HallMaster.h"
HallMaster::HallMaster(QWidget *parent, char *name)
:QWidget(parent, name)
{
mGamefaceOpened=false;
mOnline=false;
CreateSockFD();
mTimer =new QTimer(this, 0);
connect(mTimer, SIGNAL(timeout()), this, SLOT(sReceiver()));
mOpID=QString("-1");
}
HallMaster::~HallMaster()
{
}
//接收数据的函数,由QTimer类的定时器每50ms驱动一次
void HallMaster:: sReceiver()
{
int recvnum,val;
val=fcntl(mSockFD, F_GETFL, 0);
fcntl(mSockFD,F_SETFL, val|O_NONBLOCK);
int i=0;
while(i++<10)
{
recvnum=recvfrom(mSockFD, mRevBuf, BUF_LEN,0,0,0);
if(recvnum==-1)
{
//perror("recvmsg");
}
else
{
printf("int receiver received!%s\n",mRevBuf);
//通知Disposer处理信息
Disposer();
}
}
mTimer->start( 50 );
}
//将Message 格式的数据结构以udp数据包形式发送到dstaddr
int HallMaster::Sender(Message msg,struct sockaddr_in dstaddr )
{
int sockfd,sendnum,len;
char buffer[BUF_LEN];
len=mPackDisposer.MsgPacker(msg,buffer);
sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(sockfd==-1)
{
perror("socket");
exit(1);
}
sendnum =sendto(mSockFD,buffer,len,0,(struct sockaddr *)&dstaddr,sizeof(struct sockaddr));
if(sendnum<0)
{
perror("sendto");
}
buffer[sendnum]='\0';
printf("send, %s to %s, %d\n",buffer,inet_ntoa(dstaddr.sin_addr),ntohs(dstaddr.sin_port));
return 0;
}
//创建套接字,收发使用同一个socket fd
bool HallMaster::CreateSockFD()
{
int sockfd;
//准备连接
sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(sockfd==-1)
{
perror("socket");
}
mSockFD=sockfd;
}
int HallMaster::SetServerAddr(QString ip)
{
mServerAddr.sin_family=AF_INET;
mServerAddr.sin_port=htons(1500);
inet_pton(AF_INET,ip.ascii() ,&mServerAddr.sin_addr);
}
//Runner是驱动本类工作的函数
int HallMaster::Runner()
{
if(mOnline)
{
printf("still online!!!\n");
return 1;
}
mTimer->start( 50 );
mMsgToSend.mID=QString("0000");
mMsgToSend.mRequest=QString("login");
mMsgToSend.mContent=QString("F");
Sender(mMsgToSend, mServerAddr);
}
//分发器, 根据收到数据的请求调用相应函数处理,本函数由Receiver()调用
int HallMaster::Disposer()
{
Message msg;
mPackDisposer.MsgUnPacker(mMsgRecvd,mRevBuf);
//收到登录回复,得到ID
if(!mMsgRecvd.mRequest.compare(QString("login")))
{
mMyID=mMsgRecvd.mContent;
mOnline=true;
msg.mRequest=QString("hmyid");
msg.mContent=mMsgRecvd.mContent;
emit sendmsgtomain(msg);
}
//收到更新信息
else if(!mMsgRecvd.mRequest.compare(QString("update")))
UpdatePlayerTable();
//更新结束消息
else if(!mMsgRecvd.mRequest.compare(QString("endupdate")))
{
emit updatehall(); //一次性更新界面
return 5;
//5表示结束更新
}
//receive invitation, pass it to mMain to decide;
else if(!mMsgRecvd.mRequest.compare(QString("invite")))
{
msg.mRequest="hreplyinvite";
emit sendmsgtomain( msg);
}
//收到邀请回复,邀请信息在进入对局界面后按下棋盘下方"Start"时发出,"Start"按下时,先修改自己的状态为"Waiting",再发邀请
else if(!mMsgRecvd.mRequest.compare(QString("reinvite:agree")))
{
//记录对方addr,便于发送聊天信息,游戏数据
int index= mMsgRecvd.mID.toInt();
QString addr, port;
addr=mPlayerTable[index].mAddr;
port=mPlayerTable[index].mPort;
ConvertQStrToSockaddr(addr, port, mOpAddr);
//对局相关,交给Main处理
msg.mRequest=QString("hagreeinvite");
emit sendmsgtomain(msg);
}
//对方发来落子的坐标
else if(!mMsgRecvd.mRequest.compare(QString("putchess")))
{
//对局相关,交给Main处理
msg.mRequest = QString("hputchess");
msg.mContent = mMsgRecvd.mContent;
emit sendmsgtomain( msg );
}
//服务器发来换座(坐下)的回复
else if(!mMsgRecvd.mRequest.compare(QString("rechangeseat")))
{
//判断成功于否
printf("sitdown result in Content :%s\n",mMsgRecvd.mRequest.ascii());
if(mMsgRecvd.mContent.compare(QString("succeed"))==0)
//显示 交给Main下来完成,
{
msg.mRequest=QString("hchangeseat");
HandleSeatchanged(msg);
}
else
{printf("change seat failed!\n");}//提示失败
}
//对方发来聊天信息
else if(!mMsgRecvd.mRequest.compare(QString("chat")))
{
msg.mRequest = QString("recvchat");
msg.mContent = mMsgRecvd.mContent;
emit sendmsgtomain(msg);
}
else
{
printf("unknown request!\n");
}
return 123;//该返回值无特定意义
}
//获取第i号player的id
QString HallMaster::getPlayerID( int i )
{
if(i>0&&i0&&i0&&i0&&i0)
return mPlayerTable[i].mDeskNumber;
else
return QString("0");
}
//更新playertable
int HallMaster::UpdatePlayerTable()
{
//还原出一条PlayerTableNode
PlayerTableNode node;
char tempt[BUF_LEN];
strncpy(tempt,mMsgRecvd.mContent.ascii(),mMsgRecvd.mContent.length());
mPackDisposer.TableUnPacker(node,tempt);
//根据ID找到相应Player
int index;
index=node.mPlayerID.toInt();
//替换其中信息,为保持desktable一致性,先删除desktable的旧信息
int k=mPlayerTable[index].mDeskNumber.toInt();
QString lastside=mPlayerTable[index].mSide;
if(k!=0)
{
if(lastside.compare("white")==0)
mDeskTable[k].mWhiteID="-1";
else
mDeskTable[k].mBlackID="-1";
}
mPlayerTable[index].mPlayerID=node.mPlayerID;
mPlayerTable[index].mPlayerState=node.mPlayerState;
mPlayerTable[index].mPlayerOpID=node.mPlayerOpID;
mPlayerTable[index].mAddr=node.mAddr;
mPlayerTable[index].mPort=node.mPort;
mPlayerTable[index].mDeskNumber=node.mDeskNumber;
mPlayerTable[index].mSide=node.mSide;
//更新mDeskTable,保持同步
k=node.mDeskNumber.toInt(); //player所在桌号,0表示不在桌上
if(k==0)
return 0;
else
//判断方向
if(node.mSide.compare("white")==0)
mDeskTable[k].mWhiteID=node.mPlayerID;
else
mDeskTable[k].mBlackID=node.mPlayerID;
//根据mPlayerTable向mMain发送myDesk的桌位信息
index=mMyID.toInt();
k=mPlayerTable[index].mDeskNumber.toInt();
if(k==0)
return 0;
Message msg;
msg.mRequest=QString("hupdatedesk");
msg.mContent=mDeskTable[k].mWhiteID;
msg.mContent2=mDeskTable[k].mBlackID;
emit sendmsgtomain(msg);
return 0;
}
//向同一桌的对手发送邀请游戏信息
void HallMaster::HandleSendInvite()
{
//找到自己的桌位得到对方ID
int index=mMyID.toInt();
int dsknum=mPlayerTable[index].mDeskNumber.toInt();
QString id;
if(mDeskTable[dsknum].mWhiteID.compare(mMyID)==0)//找对方的id
id=mDeskTable[dsknum].mBlackID;
else
id=mDeskTable[dsknum].mWhiteID;
//根据ID查找对方地址 待改进
int i;
for(i=2; i=MAX_PLAYER)
printf("id not found!\n");
struct sockaddr_in dstaddr;
if(ConvertQStrToSockaddr( mPlayerTable[i].mAddr ,mPlayerTable[i].mPort ,dstaddr )==false)
{
printf("convertqstrtosockaddr failed!\n");
return;
}
//发送"invite"请求
Message msg;
msg.mID=mMyID;
msg.mRequest=QString("invite");
msg.mContent=id;
Sender(msg, dstaddr);
}
//将QString表示的IP地址和端口号转换成struct sockaddr, 协议一致为AF_INET
bool HallMaster::ConvertQStrToSockaddr(QString addr, QString port, struct sockaddr_in &dstaddr)
{
if(addr.ascii()==NULL||port.ascii()==NULL)
return false;
dstaddr.sin_family=AF_INET;
if(inet_pton(AF_INET, addr.ascii(), &dstaddr.sin_addr)<=0)
{
perror("inet_pton");
return false;
}
dstaddr.sin_port=htons(port.toInt());
return true;
}
//处理mMain::mChessBoard发送来的同意下棋的请求,将同意下棋邀请信息回复邀请方
void HallMaster::HandleAgreeInvite()
{
Message msg;
//得到邀请方ID,并查询对方地址
QString id=mMsgRecvd.mID;
int index=id.toInt();
QString addr=mPlayerTable[index].mAddr;
QString port=mPlayerTable[index].mPort;
//发送回复
struct sockaddr_in dstaddr;
msg.mID=mMyID;
msg.mRequest=QString("reinvite:agree");
msg.mContent="agree";
ConvertQStrToSockaddr(addr,port,dstaddr);
Sender(msg,dstaddr);
//记录对方addr
ConvertQStrToSockaddr(addr, port, mOpAddr);
}
//本方下棋后传来落子坐标,在此处理
void HallMaster::HandleChessput(Message msg)
{
//将坐标发送给对方
Message msgtosend;
msgtosend.mID=mMyID;
msgtosend.mRequest=QString("putchess");
msgtosend.mContent=msg.mContent+QString("#")+msg.mContent2+QString("#");
Sender(msgtosend, mOpAddr);
}
//坐下或换座时向服务器发送请求坐下(换座)的请求
void HallMaster:: HandleSendSitdown(QString dsknum, QString side)
{
Message msg;
msg.mID=mMyID;
msg.mRequest=QString("changeseat");
msg.mContent=dsknum+QString("&")+side+QString("&");
Sender(msg, mServerAddr);
}
//收到server回复,坐下(换座)成功,通知mMain
void HallMaster:: HandleSeatchanged(Message msg)
{
//get myside and mydesknumber
int index=mMyID.toInt();
int k=mPlayerTable[index].mDeskNumber.toInt();
if(k<=0)
return ;
QString side;
if(mDeskTable[k].mWhiteID.compare(mMyID)==0)
side=QString("white");
else
side=QString("black");
msg.mRequest=QString("hchangeseat");
msg.mContent=side;
emit sendmsgtomain(msg);
emit showgameface();
}
//向对方发送聊天内容
void HallMaster::HandleSendChat(Message msg)
{
msg.mID=mMyID;
msg.mRequest=QString("chat");
Sender(msg, mOpAddr);
}
//退出大厅时的处理函数
void HallMaster:: sonquit()
{
//check current state decide if it is valid to quit
if(mGamefaceOpened)
printf("please close gamewindow!\n");
//send request "quit" to server
Message msg;
msg.mID=mMyID;
msg.mRequest=QString("quit");
Sender(msg, mServerAddr);
//close and quit
emit quithall();
}
//处理内部消息的分发器
void HallMaster::sdisposemsg(Message msg)
{
QString req=msg.mRequest;
//mMain::mChessBoard发来同意邀请下棋的请求
if(!req.compare("bagreeinvite"))
{
HandleAgreeInvite();
}
//mMain::mChessBoard发来邀请下棋的请求,转发给对方
else if(!req.compare("bsendinvite"))
{
printf("in hallmaster::disposemsg, going to handle bsendinvite\n");
HandleSendInvite();
}
//mMain::mChessBoard 发来落子消息
else if(!req.compare("bchessput"))
{
HandleChessput(msg);
}
//Hall 发来坐下请求,转发给服务器
else if(!req.compare("hallsitdown"))
{
HandleSendSitdown(msg.mContent, msg.mContent2);
}
//mMain::mChatBox发来聊天信息
else if(!req.compare("cchat"))
{
HandleSendChat(msg);
}
//Hall 发来设置服务器地址的消息
else if(!req.compare("hallsetserveraddr"))
{
SetServerAddr( msg.mContent);
}
else
printf("hallmaster::disposemsg, unknown request! %s\n",msg.mRequest.ascii());
}