unsigned int PingRakNetServer(const char *addr, unsigned short port) { RakNet::Packet *packet; bool done = false; RakNet::TimeMS time = PING_UNREACHABLE; RakNet::SocketDescriptor socketDescriptor{0, ""}; RakNet::RakPeerInterface *peer = RakNet::RakPeerInterface::GetInstance(); peer->Startup(1, &socketDescriptor, 1); if (!peer->Ping(addr, port, false)) return time; RakNet::TimeMS start = RakNet::GetTimeMS(); while (!done) { RakNet::TimeMS now = RakNet::GetTimeMS(); if (now - start >= PING_UNREACHABLE) break; packet = peer->Receive(); if (!packet) continue; switch (packet->data[0]) { case ID_DISCONNECTION_NOTIFICATION: case ID_CONNECTION_LOST: done = true; break; case ID_CONNECTED_PING: case ID_UNCONNECTED_PONG: { RakNet::BitStream bsIn(&packet->data[1], packet->length, false); bsIn.Read(time); time = now - time; done = true; break; } default: break; } peer->DeallocatePacket(packet); } peer->Shutdown(0); RakNet::RakPeerInterface::DestroyInstance(peer); return time > PING_UNREACHABLE ? PING_UNREACHABLE : time; }
//This static method is called when the client wants to connect to the server void Session::StartClient(void * pVoid){ //A parameter list is given with needed variables ArgumentList* pArgumentList = (ArgumentList*)pVoid; RakNet::RakPeerInterface* pClient; pClient = pArgumentList->inter; SessionType type = pArgumentList->type; RakNet::RPC3* rpc3Inst = pArgumentList->rpc3; SystemAddress clientID=UNASSIGNED_SYSTEM_ADDRESS; //Register the RPC3 functions we want to call upon RPC3_REGISTER_FUNCTION(rpc3Inst, ReceiveInformation); RPC3_REGISTER_FUNCTION(rpc3Inst, UpdateCharacter); RPC3_REGISTER_FUNCTION(rpc3Inst, UpdateCharacterVelocity); RPC3_REGISTER_FUNCTION(rpc3Inst, SyncClients); RPC3_REGISTER_FUNCTION(rpc3Inst, ReceiveID); RPC3_REGISTER_FUNCTION(rpc3Inst, RemoveCharacter); //Create the basic connection with help of RakNet SocketDescriptor socketDescriptor(0,0); socketDescriptor.socketFamily=AF_INET; pClient->Startup(1,&socketDescriptor, 1); pClient->Ping( "255.255.255.255", 50000, true, 0 ); // Holds packets Packet* p; //Make sure the RPC3 is attached as a plugin, else it won't work pClient->AttachPlugin(rpc3Inst); char message[2048]; // Loop for input while (Session::threading) { // This sleep keeps RakNet responsive RakSleep(30); #ifdef _WIN32 Sleep(30); #else usleep(30 * 1000); #endif // Get a packet from either the server or the client for (p=pClient->Receive(); p; pClient->DeallocatePacket(p), p=pClient->Receive()) { switch (p->data[0]) { case ID_DISCONNECTION_NOTIFICATION: printf("ID_DISCONNECTION_NOTIFICATION\n"); break; case ID_ALREADY_CONNECTED: printf("ID_ALREADY_CONNECTED\n"); break; case ID_CONNECTION_ATTEMPT_FAILED: printf("Connection attempt failed\n"); break; case ID_NO_FREE_INCOMING_CONNECTIONS: printf("ID_NO_FREE_INCOMING_CONNECTIONS\n"); break; case ID_UNCONNECTED_PONG: // Found the server pClient->Connect(p->systemAddress.ToString(false),p->systemAddress.GetPort(),0,0,0); break; case ID_CONNECTION_REQUEST_ACCEPTED: // This tells the client they have connected printf("ID_CONNECTION_REQUEST_ACCEPTED\n"); Game::getSingletonPtr()->CreateCharacter("PlayerHost"); //Game::getSingletonPtr()->SetPlayer( break; case ID_NEW_INCOMING_CONNECTION: { printf("New incoming connection"); break; } case ID_RPC_REMOTE_ERROR: { // Recipient system returned an error switch (p->data[1]) { case RakNet::RPC_ERROR_NETWORK_ID_MANAGER_UNAVAILABLE: printf("RPC_ERROR_NETWORK_ID_MANAGER_UNAVAILABLE\n"); break; case RakNet::RPC_ERROR_OBJECT_DOES_NOT_EXIST: printf("RPC_ERROR_OBJECT_DOES_NOT_EXIST\n"); break; case RakNet::RPC_ERROR_FUNCTION_INDEX_OUT_OF_RANGE: printf("RPC_ERROR_FUNCTION_INDEX_OUT_OF_RANGE\n"); break; case RakNet::RPC_ERROR_FUNCTION_NOT_REGISTERED: printf("RPC_ERROR_FUNCTION_NOT_REGISTERED\n"); break; case RakNet::RPC_ERROR_FUNCTION_NO_LONGER_REGISTERED: printf("RPC_ERROR_FUNCTION_NO_LONGER_REGISTERED\n"); break; case RakNet::RPC_ERROR_CALLING_CPP_AS_C: printf("RPC_ERROR_CALLING_CPP_AS_C\n"); break; case RakNet::RPC_ERROR_CALLING_C_AS_CPP: printf("RPC_ERROR_CALLING_C_AS_CPP\n"); break; } printf("Function: %s", p->data+2); } } } } //When we are done as a client, close everything and delete RPC3 Session::threading = false; pClient->Shutdown(20,0); RakNet::RakPeerInterface::DestroyInstance(pClient); delete rpc3Inst; }
int main(int argc, char** argv) { RakNet::RakPeerInterface *server = RakNet::RakPeerInterface::GetInstance(); RakNet::Packet* p; unsigned char packetIdentifier; RakNet::SystemAddress clientID = RakNet::UNASSIGNED_SYSTEM_ADDRESS; RakNet::RakNetStatistics *rss; RakNet::SocketDescriptor socketDescriptors[2]; char portstring[30]; socketDescriptors[0].port = SERVER_PORT; socketDescriptors[0].socketFamily = AF_INET; // Test out IPV4 socketDescriptors[1].port = SERVER_PORT; socketDescriptors[1].socketFamily = AF_INET6; // Test out IPV6 if (server->Startup(4, socketDescriptors, 2) != RakNet::RAKNET_STARTED) { std::cout << "IPV6 not supported, starting with IPV4-only interface..." << std::endl; if (server->Startup(4, socketDescriptors, 1) != RakNet::RAKNET_STARTED) { std::cerr << "Error creating server, exiting..." << std::endl; exit(-1); } } std::cout << "Server started successfully. Listening on port " << SERVER_PORT << std::endl; server->SetMaximumIncomingConnections(20); server->SetOccasionalPing(true); server->SetUnreliableTimeout(1000); DataStructures::List<RakNet::RakNetSocket2*> sockets; server->GetSockets(sockets); std::cout << "Socket addresses used by RakNet:" << std::endl; for (unsigned int i = 0; i < sockets.Size(); i++) { printf("%i. %s\n", i + 1, sockets[i]->GetBoundAddress().ToString(true)); } char message[2048]; // Loop for input while (1) { // This sleep keeps RakNet responsive RakSleep(30); if (kbhit()) { // Notice what is not here: something to keep our network running. It's // fine to block on gets or anything we want // Because the network engine was painstakingly written using threads. Gets(message, sizeof(message)); if (strcmp(message, "quit") == 0) { puts("Quitting."); break; } if (strcmp(message, "stat") == 0) { rss = server->GetStatistics(server->GetSystemAddressFromIndex(0)); StatisticsToString(rss, message, 2); printf("%s", message); printf("Ping %i\n", server->GetAveragePing(server->GetSystemAddressFromIndex(0))); continue; } if (strcmp(message, "ping") == 0) { server->Ping(clientID); continue; } if (strcmp(message, "pingip") == 0) { printf("Enter IP: "); Gets(message, sizeof(message)); printf("Enter port: "); Gets(portstring, sizeof(portstring)); if (portstring[0] == 0) strcpy(portstring, "1234"); server->Ping(message, atoi(portstring), false); continue; } if (strcmp(message, "kick") == 0) { server->CloseConnection(clientID, true, 0); continue; } if (strcmp(message, "getconnectionlist") == 0) { printf("Connections:\n"); RakNet::SystemAddress systems[10]; unsigned short numConnections = 10; server->GetConnectionList((RakNet::SystemAddress*) &systems, &numConnections); for (int i = 0; i < numConnections; i++) { printf("%i. %s\n", i + 1, systems[i].ToString(true)); } continue; } if (strcmp(message, "ban") == 0) { printf("Enter IP to ban. You can use * as a wildcard\n"); Gets(message, sizeof(message)); server->AddToBanList(message); printf("IP %s added to ban list.\n", message); continue; } // Message now holds what we want to broadcast char message2[2048]; // Append Server: to the message so clients know that it ORIGINATED from the server // All messages to all clients come from the server either directly or by being // relayed from other clients message2[0] = 0; const static char prefix[] = "Server: "; strncpy(message2, prefix, sizeof(message2)); strncat(message2, message, sizeof(message2) - strlen(prefix) - 1); // message2 is the data to send // strlen(message2)+1 is to send the null terminator // HIGH_PRIORITY doesn't actually matter here because we don't use any other priority // RELIABLE_ORDERED means make sure the message arrives in the right order // We arbitrarily pick 0 for the ordering stream // RakNet::UNASSIGNED_SYSTEM_ADDRESS means don't exclude anyone from the broadcast // true means broadcast the message to everyone connected server->Send(message2, (const int)strlen(message2) + 1, HIGH_PRIORITY, RELIABLE_ORDERED, 0, RakNet::UNASSIGNED_SYSTEM_ADDRESS, true); } // Get a packet from either the server or the client for (p = server->Receive(); p; server->DeallocatePacket(p), p = server->Receive()) { // We got a packet, get the identifier with our handy function packetIdentifier = GetPacketIdentifier(p); // Check if this is a network message packet switch (packetIdentifier) { case ID_DISCONNECTION_NOTIFICATION: // Connection lost normally printf("ID_DISCONNECTION_NOTIFICATION from %s\n", p->systemAddress.ToString(true));; break; case ID_NEW_INCOMING_CONNECTION: // Somebody connected. We have their IP now printf("ID_NEW_INCOMING_CONNECTION from %s with GUID %s\n", p->systemAddress.ToString(true), p->guid.ToString()); clientID = p->systemAddress; // Record the player ID of the client printf("Remote internal IDs:\n"); for (int index = 0; index < MAXIMUM_NUMBER_OF_INTERNAL_IDS; index++) { RakNet::SystemAddress internalId = server->GetInternalID(p->systemAddress, index); if (internalId != RakNet::UNASSIGNED_SYSTEM_ADDRESS) { printf("%i. %s\n", index + 1, internalId.ToString(true)); } } break; case ID_INCOMPATIBLE_PROTOCOL_VERSION: printf("ID_INCOMPATIBLE_PROTOCOL_VERSION\n"); break; case ID_CONNECTED_PING: case ID_UNCONNECTED_PING: printf("Ping from %s\n", p->systemAddress.ToString(true)); break; case ID_CONNECTION_LOST: // Couldn't deliver a reliable packet - i.e. the other system was abnormally // terminated printf("ID_CONNECTION_LOST from %s\n", p->systemAddress.ToString(true));; break; default: // The server knows the static data of all clients, so we can prefix the message // With the name data printf("%s\n", p->data); // Relay the message. We prefix the name for other clients. This demonstrates // That messages can be changed on the server before being broadcast // Sending is the same as before sprintf(message, "%s", p->data); server->Send(message, (const int)strlen(message) + 1, HIGH_PRIORITY, RELIABLE_ORDERED, 0, p->systemAddress, true); break; } } } server->Shutdown(300); // We're done with the network RakNet::RakPeerInterface::DestroyInstance(server); }
int main(void) { // Pointers to the interfaces of our server and client. // Note we can easily have both in the same program RakNet::RakPeerInterface *client; RakNet::RakPeerInterface *server; bool b; char str[256]; char serverPort[30], clientPort[30]; RakNet::TimeMS quitTime; // Holds packets RakNet::Packet* p; printf("A client / server sample showing how clients can broadcast offline packets\n"); printf("to find active servers.\n"); printf("Difficulty: Beginner\n\n"); printf("Instructions:\nRun one or more servers on the same port.\nRun a client and it will get pongs from those servers.\n"); printf("Run as (s)erver or (c)lient?\n"); Gets(str, sizeof(str)); if (str[0]=='s' || str[0]=='S') { client=0; server=RakNet::RakPeerInterface::GetInstance(); // A server printf("Enter the server port\n"); Gets(serverPort,sizeof(serverPort)); if (serverPort[0]==0) strcpy(serverPort, "60001"); printf("Starting server.\n"); // The server has to be started to respond to pings. RakNet::SocketDescriptor socketDescriptor(atoi(serverPort),0); socketDescriptor.socketFamily=AF_INET; // Only IPV4 supports broadcast on 255.255.255.255 b = server->Startup(2, &socketDescriptor, 1)==RakNet::RAKNET_STARTED; server->SetMaximumIncomingConnections(2); if (b) printf("Server started, waiting for connections.\n"); else { printf("Server failed to start. Terminating.\n"); exit(1); } } else { client=RakNet::RakPeerInterface::GetInstance(); server=0; // Get our input printf("Enter the client port to listen on, or 0\n"); Gets(clientPort,sizeof(clientPort)); if (clientPort[0]==0) strcpy(clientPort, "60000"); printf("Enter the port to ping\n"); Gets(serverPort,sizeof(serverPort)); if (serverPort[0]==0) strcpy(serverPort, "60001"); RakNet::SocketDescriptor socketDescriptor(atoi(clientPort),0); socketDescriptor.socketFamily=AF_INET; // Only IPV4 supports broadcast on 255.255.255.255 client->Startup(1, &socketDescriptor, 1); // Connecting the client is very simple. 0 means we don't care about // a connectionValidationInteger, and false for low priority threads // All 255's mean broadcast client->Ping("255.255.255.255", atoi(serverPort), false); printf("Pinging\n"); } printf("How many seconds to run this sample for?\n"); Gets(str, sizeof(str)); if (str[0]==0) { printf("Defaulting to 5 seconds\n"); quitTime = RakNet::GetTimeMS() + 5000; } else quitTime = RakNet::GetTimeMS() + atoi(str) * 1000; // Loop for input while (RakNet::GetTimeMS() < quitTime) { if (server) p = server->Receive(); else p = client->Receive(); if (p==0) { RakSleep(30); continue; } if (server) server->DeallocatePacket(p); else { if (p->data[0]==ID_UNCONNECTED_PONG) { RakNet::TimeMS time; RakNet::BitStream bsIn(p->data,p->length,false); bsIn.IgnoreBytes(1); bsIn.Read(time); printf("Got pong from %s with time %i\n", p->systemAddress.ToString(), RakNet::GetTimeMS() - time); } else if (p->data[0]==ID_UNCONNECTED_PING) { printf("ID_UNCONNECTED_PING from %s\n",p->guid.ToString()); } else if (p->data[0]==ID_UNCONNECTED_PING_OPEN_CONNECTIONS) { printf("ID_UNCONNECTED_PING_OPEN_CONNECTIONS from %s\n",p->guid.ToString()); } client->DeallocatePacket(p); } RakSleep(30); } // We're done with the network if (server) RakNet::RakPeerInterface::DestroyInstance(server); if (client) RakNet::RakPeerInterface::DestroyInstance(client); return 0; }