📄 gobangsrv.cpp
字号:
#include "gobangSrv.h"#include "client.h"using namespace std;void sg_hd(int signum);vector<client> clivec;int maxfd;fd_set rset, wset;pair<int, int> pos;char chatBuff[MAX_LEN * 20];char flagInfo;char nextTurn;int x, y;char chessBoard[15][15];int newclient(int listenfd);char recv(fd_set& rs);int send(char* sendbuff, fd_set &ws);int NewGame();int SendFlagInfo();bool SendErroInfo(char wrongType, char sendDestine);bool PositionRight(void);bool SendPosInfo(char sendDestine);int checkLength(int x, int y, int direction);bool CheckVicCon();bool SendVicInfo();int main(int argc, char* argv[]){ int listenfd; struct sockaddr_in servaddr; sigset_t block_mask, zero_mask; struct sigaction sg_act, old_sa; if(argc < 2) { cout << "usage: crsrv <port>\n"; exit(0); } bzero(&sg_act, sizeof(struct sigaction)); bzero(&old_sa, sizeof(struct sigaction)); sigemptyset(&block_mask); sigemptyset(&zero_mask); sg_act.sa_mask = block_mask; sg_act.sa_flags = 0; sg_act.sa_handler = sg_hd; if(sigaction(SIGCHLD, &sg_act, NULL) == -1) { perror("sigaction"); exit(1); } if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(atoi(argv[1])); if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1) { perror("bind"); exit(1); } if(listen(listenfd, BACKLOG) ==-1) { perror("listen"); exit(1); } for( ; ; ) { maxfd = listenfd + 1; newclient(listenfd); if(clivec.size() >= 2) { pid_t pid; pid = fork(); cout << "fork\n"; if(pid < 0) { perror("fork"); } else if (pid ==0) { close(listenfd); NewGame(); } else if (pid > 0) { close(clivec[0].clifd); close(clivec[1].clifd); clivec.clear(); } } } return 0;}void sg_hd(int signum){ int status; if(signum == SIGCHLD) { while(waitpid(-1, &status, WNOHANG) > 0); cout << "Child exit\n"; return; } if(signum == SIGALRM) { cout << "Child " << getpid() << " get time alarmed\n"; exit(0); }}int newclient(int listenfd){ int connfd; struct sockaddr_in cliaddr; socklen_t clilen; clilen = sizeof(cliaddr); connfd = accept(listenfd, (struct sockaddr*)&cliaddr, &clilen); if(connfd == -1) { if(errno == EINTR) { return -1; } else if(errno == EWOULDBLOCK) { return -2; } else { perror("accept"); return -3; } } else { client newclnt; newclnt.clifd = connfd; cout << "new client\n"; clivec.push_back(newclnt); return 0; }}char recv(fd_set& rs){ vector<client>::iterator iter; int n; char buff[MAX_LEN]; for(iter = clivec.begin(); iter !=clivec.end(); iter++) { if(FD_ISSET(iter->clifd, &rs)) { bzero(buff, MAX_LEN); if((n = iter->recv(buff, MAX_LEN)) == -3) { cout << iter->name << " recv wrong\n"; continue; } else if(n == 0)//client leave the chat room { snprintf(buff, MAX_LEN, "%s leave the serve\n", iter->name); FD_CLR(iter->clifd, &wset); FD_CLR(iter->clifd, &rset); close(iter->clifd); cout << buff; clivec.erase(iter); strncat(chatBuff, buff, MAX_LEN * 20); return LEAVE_INFO; } else if(n > 0) { buff[n] = '\0'; switch(buff[0]) { case NAME_INFO: return NAME_INFO; case POS_INFO: cout << "recv flag "<< (unsigned)nextTurn << '\t' << (unsigned)iter->flagStatus << '\n'; if(iter->flagStatus == nextTurn) { pos.first = buff[1]; pos.second = buff[2]; cout << "pos:" << pos.first << '\t' << pos.second << '\n'; x = pos.first; y = pos.second; return POS_INFO; } else return WRONG_SIDE; case CHAT_INFO: strncat(chatBuff, iter->recvhead, MAX_LEN * 20); strncat(chatBuff, buff + 1, MAX_LEN * 20); break; case FLAG_INFO: flagInfo = buff[1]; return FLAG_INFO; default: return WRONG_INFO; } } } } return CHAT_INFO;}int sendChatInfo(fd_set& ws){ vector<client>::iterator iter; for(iter = clivec.begin(); iter != clivec.end(); iter++) { if(FD_ISSET(iter->clifd, &ws)) { if(iter->send(chatBuff, MAX_LEN) == -3) { cout << iter->name << " send wrong\n"; return -1; } } } return 0;}int NewGame(){ client black, white; pair<int, int> pos;//pos[0] = x; pos[2] = y char recvResult; FD_ZERO(&rset); FD_ZERO(&wset); vector<client>::iterator iter; for(iter = clivec.begin(); iter !=clivec.end(); iter++) { iter->getname(); iter->nonblock(); FD_SET(iter->clifd, &rset); FD_SET(iter->clifd, &wset); if(iter->clifd + 1 > maxfd) maxfd = iter->clifd + 1; cout << "game:" << getpid() << "\tuser:"<< iter->name << '\n'; } SendFlagInfo(); //cout << (unsigned)clivec[0].flagStatus << '\t' << (unsigned)clivec[1].flagStatus << '\n'; nextTurn = BLACK; for(int i = 0; i < 15; i++) { for(int j =0; j< 15; j++) { chessBoard[i][j] = CHESSBOARD_EMPYT; } } fd_set rs, ws; for( ; ; ) { rs = rset; bzero(chatBuff, sizeof(chatBuff)); chatBuff[0] = CHAT_INFO; //cout << "selecting maxfd:" << maxfd << '\n'; if(select(maxfd, &rs, NULL, NULL, NULL) == -1) { if(errno == EINTR) { continue; } else { perror("select"); exit(1); } } recvResult = recv(rs); if(recvResult == CHAT_INFO) { if(strlen(chatBuff) > 0) { ws = wset; if(select(maxfd, NULL, &ws, NULL, NULL) == -1) { if(errno == EINTR) { continue; } else { perror("select"); exit(1); } } sendChatInfo(ws); } } else if(recvResult == POS_INFO) { if(PositionRight()) { //cout << "\tSet " << x << '\t' << y << " to " << (unsigned)nextTurn << '\n'; chessBoard[x][y] = nextTurn; if(!CheckVicCon()) { if(nextTurn == BLACK) nextTurn = WHITE; else if(nextTurn == WHITE) nextTurn = BLACK; SendPosInfo(nextTurn); } else { SendVicInfo(); } } else { SendErroInfo(WRONG_POSITION, nextTurn); } } else if(recvResult == LEAVE_INFO && clivec.size() < 2) { vector<client>::iterator iter; for(iter = clivec.begin(); iter !=clivec.end(); iter++) { FD_CLR(iter->clifd, &wset); FD_CLR(iter->clifd, &rset); close(iter->clifd); clivec.erase(iter); } exit(0); } } }int SendFlagInfo(){ srand(time(NULL)); int gambleResult = rand() % 2; char whiteName[MAXCLNTNAME], blackName[MAXCLNTNAME]; if(gambleResult == 0) { clivec[0].flagStatus = BLACK;//black clivec[1].flagStatus = WHITE;//write strncpy(whiteName, clivec[1].name, MAXCLNTNAME); strncpy(blackName, clivec[0].name, MAXCLNTNAME); } else { clivec[0].flagStatus = WHITE; clivec[1].flagStatus = BLACK; strncpy(whiteName, clivec[0].name, MAXCLNTNAME); strncpy(blackName, clivec[1].name, MAXCLNTNAME); } char buff[MAX_LEN]; //cout << "name:\t" << whiteName << "\t" << blackName << '\n'; vector<client>::iterator iter; for(iter = clivec.begin(); iter !=clivec.end(); iter++) { bzero(buff, MAX_LEN); buff[0] = FLAG_INFO; buff[1] = iter->flagStatus; if(iter->flagStatus == WHITE) { strncat(buff, blackName, MAX_LEN); } else if(iter->flagStatus == BLACK) { strncat(buff, whiteName, MAX_LEN); } if(iter->send(buff, strlen(buff)) == -3) { perror("Send flag"); return 0; } } return 1;}bool SendErroInfo(char wrongType, char sendDestine){ char buff[2]; buff[0] = WRONG_INFO; buff[1] = wrongType; vector<client>::iterator iter; for(iter = clivec.begin(); iter !=clivec.end(); iter++) { if(sendDestine == ALL) { if(iter->send(buff, 2) == -3) { perror("Send error Info"); return false; } } else if(iter->flagStatus == sendDestine) { if(iter->send(buff, 2) == -3) { perror("Send error Info"); return false; } } } return true;}bool PositionRight(){ return chessBoard[x][y] == CHESSBOARD_EMPYT;}bool SendPosInfo(char sendDestine){ char buff[3]; buff[0] = POS_INFO; buff[1] = (char)pos.first; buff[2] = (char)pos.second; vector<client>::iterator iter; for(iter = clivec.begin(); iter !=clivec.end(); iter++) { //cout << "send flag "<< (unsigned)sendDestine << '\t' << (unsigned)iter->flagStatus << '\n'; if(iter->flagStatus == sendDestine) { if(iter->send(buff, 3) == -3) { perror("Send error Info"); return false; } //cout << "Pos send to " << (unsigned)sendDestine << '\t' << pos.first << '\t' << pos.second << '\n'; } } return true;}bool CheckVicCon(){ int length[8]; for(int direction = 0; direction < 8; direction ++) { length[direction] = checkLength(pos.first, pos.second, direction); //cout << "length:\t"; //for(int j = 0; j <= direction; j++) //{ // cout << length[direction] <<'\t'; //} //cout << '\n'; if(direction >= 4 && (length[direction] + length[direction - 4]) > 5) return true; } return false;}int checkLength(int x, int y, int direction){ int length = 1; int nextX, nextY; nextX = x; nextY = y; for(int i = 0; i < 15 ; i++) { switch(direction) { case 0: nextX = nextX - 1; nextY = nextY - 1; break; case 1: nextX = nextX; nextY = nextY - 1; break; case 2: nextX = nextX + 1; nextY = nextY - 1; break; case 3: nextX = nextX + 1; nextY = nextY; break; case 4: nextX = nextX + 1; nextY = nextY + 1; break; case 5: nextX = nextX; nextY = nextY + 1; break; case 6: nextX = nextX - 1; nextY = nextY + 1; break; case 7: nextX = nextX - 1; nextY = nextY; break; } //cout << "Length extend pos x: "<< nextX << " y: " << nextY << '\n'; //cout << "Chess board status:" << (unsigned)chessBoard[nextX][nextY] << " Next Turn " << (unsigned)nextTurn << '\n'; if(nextX >= 15 || nextX < 0 || nextY < 0 || nextY >= 15) break; if(chessBoard[nextX][nextY] == nextTurn) { length++; } else break; } return length;}bool SendVicInfo(){ char buff[4]; buff[0] = VIC_INFO; buff[1] = nextTurn; buff[2] = (unsigned)pos.first; buff[3] = (unsigned)pos.second; vector<client>::iterator iter; for(iter = clivec.begin(); iter !=clivec.end(); iter++) { //cout << "Victory " << (int)nextTurn << "\tSend to " << (unsigned)iter->flagStatus << '\n'; if(iter->send(buff, 4) == -3) { perror("Send error Info"); return false; } } return true;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -