void Server::run() { next_update = 0; next_move = 0; if (socket.bind(port) != sf::Socket::Done) { cout << "Coudn't start server: bind failed" << endl; return; } cout << "Server is listening to port " << port << endl; cout << "Protocol message size: " << sizeof(Message) << endl; socket.setBlocking(false); char in[sizeof(Message)]; memset(in, '\0', sizeof(Message)); std::size_t received; sf::IpAddress sender; unsigned short senderPort; sf::Clock clock; int previous = clock.getElapsedTime().asMilliseconds(); game_data = vector<ServerSnake>(0); food = vector<Part>(0); while (true) { sf::Socket::Status s = socket.receive(in, sizeof(in), received, sender, senderPort); if (received != 0) { Message got = Protocol::decode(in); if (got.t < Message::MAX) { //cout << (string)sender.toString() << endl; //cout<< to_string(senderPort) << endl; string UUID = (string)(sender.toString() + to_string(senderPort)); if (got.t == Message::JOIN) { User newUser; newUser.ip = sender; newUser.port = senderPort; newUser.sID = game_data.size(); users[UUID] = newUser; ServerSnake tempSnake; tempSnake.dead = false; tempSnake.parts = std::vector<Part>(0); int div = game_data.size() % 4; int x0 = (rand() % (WIDTH / 2 - MIN_PARTS)) + MIN_PARTS; int dx = -1; if (div > 1) { dx = 1; //x0 += WIDTH / 2; } int y0 = rand() % (HEIGHT / 2); if (div % 2 == 1) y0 += HEIGHT / 2; for (int i = 0; i < MIN_PARTS; i++) { tempSnake.parts.push_back({ (char)(x0 + i * dx), char(y0) }); } if (dx == 1) tempSnake.direction = LEFT; else tempSnake.direction = RIGHT; game_data.push_back(tempSnake); cout << "NEW USER Current users: " << users.size() << endl; } if (users.count(UUID)>0) { User *u = &users[UUID]; Message tobroadcast=Protocol::make(Message::NONE); Message res = u->message(got,game_data, tobroadcast, food); if (tobroadcast.t!=Message::NONE) broadcast(UUID, tobroadcast); if (res.t != Message::NONE) socket.send(Protocol::encode(res), sizeof(Message) , u->ip, u->port); } if (got.t == Message::MOVE) { for (int i = 0; i < game_data.size(); i++) { if (users[UUID].sID == i) { game_data[i].direction = got.As.move.direction; } } } } } int current = clock.getElapsedTime().asMilliseconds(); if (current != previous) { int steps = current - previous; if (users.size() > 0) { next_update += steps; if (next_update > UPDATEEVERY) { update(); broadcastAll(Protocol::update(game_data, food)); next_update -= UPDATEEVERY; } } previous = current; } } }
int main(){ int newfd; struct sockaddr_storage remoteaddr; socklen_t addrlen; char buf[800]; int nbytes; char remoteIP[INET6_ADDRSTRLEN]; int yes = 1; int i, j; struct addrinfo hints, *ai, *ai_itr; FD_ZERO(&master); FD_ZERO(&read_fds); memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; int rv; if (rv = getaddrinfo(NULL, PORT, &hints, &ai)){ fprintf(stderr, "server: %s\n", gai_strerror(rv)); exit(1); } for(ai_itr = ai; ai_itr!=NULL; ai_itr = ai_itr->ai_next) { listener = socket(ai_itr->ai_family, ai_itr->ai_socktype, ai_itr->ai_protocol); if(listener < 0) { continue; } setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); if (bind(listener, ai_itr->ai_addr, ai_itr->ai_addrlen) <0 ){ close(listener); continue; } break; } if (ai_itr == NULL) { fprintf(stderr, "server: failed to bind\n"); exit(2); } freeaddrinfo(ai); if (listen(listener, 10) == -1) { perror("listen"); exit(3); } FD_SET(listener, &master); fdmax = max(fdmax, listener); sigset_t mask; sigset_t orig_mask; struct sigaction act; memset(&act, 0, sizeof act); act.sa_handler = sigint_handler; sigaction(SIGINT, &act, 0); sigemptyset(&mask); sigaddset(&mask, SIGINT); sigprocmask(SIG_BLOCK, &mask, &orig_mask); while(1){ read_fds = master; int res; if ( (res=pselect(fdmax+1, &read_fds, NULL, NULL, NULL,&orig_mask)) == -1) { if(errno!=EINTR){ perror("select"); exit(4);} } else if(!res){ printf("Res == 0\n"); } if(got_int){ bool hasconnected = false; do{ printf("Cleaning up\n"); hasconnected = false; for(i = 0; i<=fdmax; i++){ if(FD_ISSET(i, &read_fds) && i!=listener && ol_list[i]){ char b[200] = {}; mmsend(i, "[SHUTDOWN]\n"); int x = recv(i, b, sizeof b, 0); if(x>0){ mmsend(i, "[SHUTDOWN]\n"); } if(!x){ printf("%d %s closed.\n", i, user_list[i]); user_list[i][0] = 0; ol_list[i] = 0; ip_list[i][0] = 0; } hasconnected = true; } } } while(hasconnected); printf("Closed all\n"); return 0; } for(i = 0; i<=fdmax; i++) { if (FD_ISSET(i, &read_fds)) { if (i == listener) { // new connection if(got_int) continue; addrlen = sizeof remoteaddr; newfd = accept(listener, (struct sockaddr *)&remoteaddr, &addrlen); if(newfd == -1 && !got_int) { if(errno != EINTR) perror("accept"); } else { FD_SET(newfd, &master); fdmax = max(fdmax, newfd); printf("server: %s connected on socket %d\n", inet_ntop(remoteaddr.ss_family, get_in_addr((struct sockaddr *)&remoteaddr), remoteIP, INET6_ADDRSTRLEN), newfd); strcpy(ip_list[newfd], remoteIP); user_list[newfd][0] = 0; ol_list[newfd] = 0; } } else { // handle data from client if ( (nbytes = recv(i, buf, sizeof buf, 0)) <= 0 ) { if (nbytes == 0 ){ // connection closed printf("server: (%s) on socket %d hung up\n", ip_list[i], i); close(i); ip_list[i][0] = 0; user_list[i][0] = 0; ol_list[i] = 0; FD_CLR(i, &master); // broadcast here } else { if(errno!=EINTR) perror("recv"); } } else { // broadcast here char ret[800]; currfd = i; int bm = handle_data(buf, ret); if(bm == BROADCAST_SELF){ msend(i, ret, strlen(ret), 0); } else if(bm == BROADCAST_OTHERS){ broadcastOthers(ret, i); } else if(bm == BROADCAST_ALL){ broadcastAll(ret); } else { broadcastOne(ret); } } } // END handle data from client } } // END for loop iteration through file descriptors } // END while loop return 0; }