📄 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数据包形式发送到dstaddrint 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 fdbool 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的idQString HallMaster::getPlayerID( int i ){ if(i>0&&i<MAX_PLAYER) return mPlayerTable[i].mPlayerID; else return QString("0");} //获取第i号player的座位号, "0"表示还没坐下QString HallMaster::getPlayerDesknumber( int i ){ if(i>0&&i<MAX_PLAYER) return mPlayerTable[i].mDeskNumber; else return QString("0");} //获取i号桌白方IDQString HallMaster :: getDeskWhiteside(int i){ if(i>0&&i<MAX_DESK) return mDeskTable[i].mWhiteID; else return QString("0");}//获取I号桌黑方idQString HallMaster::getDeskBlackside(int i){ if(i>0&&i<MAX_DESK) return mDeskTable[i].mBlackID; else return QString("0"); }QString HallMaster::getMyID(){ return mMyID;}QString HallMaster::getMyDesknumber(){ int i=0; i=mMyID.toInt(); if(i>0) return mPlayerTable[i].mDeskNumber; else return QString("0");}//更新playertableint 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; i++) { if(mPlayerTable[i].mPlayerID.compare(id)==0) break; } if(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_INETbool 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回复,坐下(换座)成功,通知mMainvoid 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());}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -