Programmera spel i C++ för nybörjare/Nätverksprogrammering 1
Kodexemplen bygger på VC++ 2010 och SFML 1.6
Nätverksprogrammering i C++ är inte kul, kanske främst för att nätverk med datorer inte var vanliga när C++ utvecklades. Det gör att det inte finns någon riktig standard. Om man programmerar i Java, Ruby, Python eller C# finns inbyggda bibliotek för att hantera nätverksprotokoll, men inte i C++. Av den anledningen är det svårare att skriva nätverksbaserade program med C++ än med nyare språk. För att göra det än mer besvärligt har man olika standard för systemkommandon, som nätverket tillhör, i Windows, Linux och Macintosh så den kod som fungerar för nätverk i ett system misslyckas i ett annat.
Open GL och därmed SFML har tagit fram ett enkelt ramverk för nätverksprogrammering för att komma runt problemet. Det följer de få standarder som finns och skall skapa kod som fungerar på alla tre plattformarna. Det fungerar däremot inte bra utanför utvecklingsmiljön SFML. Så det du lär dig i nätverksprogrammering i SFML går inte automatiskt att föra över till nätverksprogrammering i VC++, till exempel. Med det sagt, var tacksam över det SFML ger dig; ett förhållandevis enkelt ramverk för att skapa kontakt mellan datorer så att det går att skapa nätverksspel som fungerar likadant i Windows, Linux och Macintosh.
Vad kan man då göra med SFML:s nätverksbibliotek?
- Ansluta datorer till varandra med UDP protokollet
- Ansluta datorer till varandra med TCP protokollet
- Bearbeta skickad- och mottagen information med inbyggd pakethantering
- Hantera filer på Internet med HTTP protokollet
- Hantera filer på Internet med FTP protokollet
I realiteten kan du alltså göra rätt avancerade nätverksprogram som inte har ett dyft med spel att göra med hjälp av de nätverksbibliotek som ingår i SFML, på ett bra mycket enklare sätt än man kan göra med hjälp av "vanlig" C++.
SFML och nätverksbiblioteket
[redigera]Det första du måste göra är att se till så att även nätverksmodulerna länkas in till SFML. Optimalt, om alla moduler som finns i SFML är inlänkade till Visual C++, skall det stå:
sfml-system-s-d.lib sfml-window-s-d.lib sfml-graphics-s-d.lib sfml-audio-s-d.lib sfml-network-s-d.lib
i debug mode, och sedan för release:
sfml-system-s.lib sfml-window-s.lib sfml-graphics-s.lib sfml-audio-s.lib sfml-network-s.lib
Sockets
[redigera]En direktöversättning av ordet "sockets" skulle kunna vara "kontaktuttag" och det är egentligen precis vad det handlar om. När du skapar en "socket" skapar du en kontaktanslutning baserad på en "port" i datorn. Sedan finns det förhoppningsvis något annat program därute som också har ett likadant kontaktuttag. När dessa två uttag kopplas ihop har man en kontakt mellan datorerna.
Det finns många olika sorters "sockets" men när man jobbar med nätverksspel i SFML är det egentligen bara två olika som används:
- UDP = snabbt och enkelt, men saknar "kvittering". Det man skickar med UDP är litet som att man skickar iväg ett vykort. Man har skrivit en adress på det och hoppas att det kommer fram till adressen, men det finns ingen garanti och det går inte att kontrollera heller.
- TCP = mer komplicerat men ger en kvittens så att det går att kontrollera överföringen av information från sändardatorn. Det är litet som ett telefonsamtal, mottagaren och sändaren kan hela tiden avgöra om det finns en kontakt.
När skall man använda vilken sort?
[redigera]Enkelt sagt fungerar UDP bäst i små spel där man kan anta att alla spelare sitter bredvid varandra eller i samma rum. Alternativt för spel med hundratals eller tusentals kontakter i sekunden som t.ex. LOTRO (Lord of the Rings Online) där mängder av spelare spelar samtidigt i samma värld. TCP används till mer avancerade spel där man inte kan ropa fysiskt till alla uppkopplade spelare för att se om de kan få kontakt. TCP är mindre lämpligt i spel med mängder av informationsöverföringar då det skickar en kvittens som drar ner hastigheten. UDP är friare och ungefär som ett rop i nätverket. Alla som har ett program som lyssnar på samma port hör ropet. Med TCP måste man ha en förbindelse först innan man ropar och då är det bara datorn man är uppkopplad mot som hör ropet, vilket även gör TCP säkrare om informationen är känslig.
Portar
[redigera]Vilka portar i datorn skall man använda? Alla portar under portnummer 1024 är redan låsta av olika standardprogram och tjänster. Portar från 1024 till 49151 är öppna att använda. Det finns dock en hel del undantag. Du kan själv se olika exempel på hur olika portar används på Wikipedia så att du kan undvika ett portnummer som redan används:
http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
IP-numret
[redigera]Alla datorer på Internet eller i nätverk har ett IP-nummer, en IP-adresss. Det kan vara krångligt att lista ut, men som tur är finns det ett flertal inbyggda funktioner i SFML som visar vilket IP-nummer/adress du har och hur man tar kontakt med andra datorer baserat på deras IP nummer. Du skapar en SFML IP-adress instans med:
sf::IPAddress Address1;
Sedan kan du ange vad Adress1 skall vara på något av följande sätt:
sf::IPAddress Address1("192.168.0.1"); // Från en string/text sf::IPAddress Address1("datornamn"); // Om du vet namnet på din dator sf::IPAddress Address1(192, 168, 0, 1); // ¨Från fyra olika byte/integers som är kända sedan tidigare sf::IPAddress Address1 = sf::IPAddress::LocalHost; // 127.0.0.1 -- din egen dator
Vill du ta fram din egen IP adress skriver du:
sf::IPAddress Address1 = sf::IPAddress::GetLocalAddress();
Då får du fram din egen lokala adress som du också kan få fram med kommandot ipconfig i konsollfönstret i Windows (eller Linux). Om du däremot vill få fram det IP nummer som du har utåt, mot Internet, är det besvärligare och tar mycket längre tid eftersom det måste kontrolleras mot någon tjänst ute på Internet. Kommandot är:
sf::IPAddress Address1 = sf::IPAddress::GetPublicAddress();
Och slutligen, om du vill skriva ut ditt IP nummer så att du kan kontrollera vad du har kan du skriva:
std::string IP = Address1.ToString(); std::cout<<"Adressen är = " << IP << std::endl;
IP kodexempel
[redigera]#include <iostream> #include <SFML/System.hpp> #include <SFML/Network.hpp> #define SFML_STATIC //Se till så att det inte behövs extra DLL-filer int main (int argc, char **argv) { //Visa upp lokal adress, troligen 192.168.x.x eller 10.100.x.x sf::IPAddress Address1 = sf::IPAddress::GetLocalAddress(); std::string IP1 = Address1.ToString(); std::cout<<"Din lokala adress är = " << IP1 << std::endl; //Visar upp den adress man ser utifrån internet sf::IPAddress Address2 = sf::IPAddress::GetPublicAddress(); std::string IP2 = Address2.ToString(); std::cout<<"Din adress mot Internet är = " << IP2 << std::endl; // std::cin.ignore(10000, '\n'); //Om du vill, förhindrar att fönstret stängs direkt return 0; }
UDP sockets
[redigera]Man skapa en ny UDP socket med:
sf::SocketUDP Socket;
I SFML lägger man informationen man vill skicka med en UDP socket i en array (OBS! detta gäller alltså INTE generellt för C++ programmering), så om man vill skicka ett textmeddelande vi kallar Buffer kan man preparera det med:
char Buffer[] = "Ett meddelande!";
Anta sedan att vi vill skicka meddelandet ut till en dator på nätverket som vi känner till IP adressen för. Om IP numret är 192.168.0.2 och porten vi vill använda t.ex. 4567 skriver vi:
if (Socket.Send(Buffer, sizeof(Buffer), "192.168.0.2", 4567) != sf::Socket::Done) { // Error... }
Alla portnummer från 1024 och neråt är som sagt upptagna, men portarna över är fria att använda för programmerare. Undvik dock port nummer 8080 eftersom många företag satt den som HTTP port istället för standard 80.
Socket status
[redigera]I exemplet står det sf::Socket::Done och det beror på att en socket kan ha en, av fyra, olika statusar (se mer om du söker på sf::Socket::Status) :
sf::Socket::Done : Operationen har lyckats och avslutats. sf::Socket::NotReady : Enbart i ej blockerande läge, det svar man får tillbaka om socketen inte är klar att användas ännu. (Blockerande läge blocking mode är standard, då måste man ta emot något innan man kan skicka något) sf::Socket::Disconnected : Socketen har kopplats bort. sf::Socket::Error : Ett oväntat fel har uppstått.
Ta emot information
[redigera]För att kunna lyssna av en port måste först programmet koppla porten till sig, eller binda den till sig, som man också kan säga. Man skapar en ny UDP socket med:
sf::SocketUDP Socket;
Om man sedan skall lyssna på just port 4567 skriver man:
if (!Socket.Bind(4567)) { // Error... }
När man lyssnar på porten och tar emot information måste man också kunna tolka den information som kommer.
char Buffer[128]; //Skapa en motsvarande array som sändaren har std::size_t Received; //Storleken på den information som mottagits sf::IPAddress Sender; //Sändarens IP-adress unsigned short Port; //Porten som informationen kommer från if (Socket.Receive(Buffer, sizeof(Buffer), Received, Sender, Port) != sf::Socket::Done) { // Error... } // Visa avsändarens adress / port std::cout << Sender << ":" << Port << std::endl; // Visa meddelandet std::cout << Buffer << std::endl; // "Ett meddelande!"
När du är klar med din socket bör du stänga den utifall att det finns andra program i datorn som vill använda samma port:
Socket.Close();
TCP sockets
[redigera]Man skapar en ny TCP socket litet annorlunda eftersom den måste ha en bekräftad uppkoppling mot den andra datorn innan den börjar att skicka information. Anta att vi vill skapa en TCP socket som vi kallat lyssnare, eller Listener. Då skriver vi:
sf::SocketTCP Listener; if (!Listener.Listen(4567)) { // Error... }
Sedan är det bara att vänta som en katt utanför ett råtthål på att någon vill koppla upp sig mot dig på port 4567:
sf::IPAddress ClientAddress; sf::SocketTCP Client; if (Listener.Accept(Client, &ClientAddress) != sf::Socket::Done) { // Error... }
"Accept" är en funktion som är ansvarig för själva uppkopplingen. ClientAddress är IP numret på den som kopplar upp sig.
Om man sedan vill koppla up sig mot den här TCP servern skapar man en TCP port och försöker att ansluta till den port som servern lyssnar på:
sf::SocketTCP Client; if (Client.Connect(4567, "192.168.0.2") != sf::Socket::Done) { // Error... }
När båda skakat hand utan "Error" kan man börja utbyta information mellan varandra. Den enda skillnaden mot att använda UDP är att man inte behöver fylla i IP- och portnummer (eftersom det redan gjorts vid anslutningen). Vill man skicka ett meddelande till servern kan man alltså skriva:
char Buffer[] = "Ett meddelande!"; if (Client.Send(Buffer, sizeof(Buffer)) != sf::Socket::Done) { // Error... }
Servern kan sedan koda av det med:
char Buffer[128]; std::size_t Received; if (Client.Receive(Buffer, sizeof(Buffer), Received) != sf::Socket::Done) { // Error... }
Till skillnad från UDP kan Send och Receive med TCP också ge svaret "Disconnected" som visar att anslutningen av någon anledning avbrutits.
När man är klar med uppkopplingen måste man, precis som med UDP, stänga socketen så att andra program kommer åt porten.
Kodexempel, UDP och TCP test av kontakt mellan datorer
[redigera]Om du kör det här lilla programmet i Windows kommer du troligtvis att vara tvungen att godkänna det i brandväggen också, annars kommer Windows att stoppa alla kontakter till- eller från programmet. De enda modulerna som används i kodexemplet är system- och nätverksmodulen i SFML.
#include <iostream> //Enbart system- och nätverksmodulerna används #include <SFML/System.hpp> #include <SFML/Network.hpp> // MÅSTE finnas med för nätverksspel #define SFML_STATIC //Se till så att det inte behövs extra DLL-filer // using namespace std; // utifall att konsollen behövs för felsöknning // Funktionsdeklarationer void DoClientTCP(unsigned short Port); void DoClientUDP(unsigned short Port); void DoServerTCP(unsigned short Port); void DoServerUDP(unsigned short Port); int main (int argc, char **argv) { // Välj valfritt nummer över 1024 för port, de < 1024 är reserverade const unsigned short Port = 2435; // TCP eller UDP ? char Protocol; std::cout << "Vill du använda TCP ('t') eller UDP ('u') ? "; std::cin >> Protocol; // Klient eller server ? char Who; std::cout << "Vill du vara server ('s') eller en klient ('k') ? "; std::cin >> Who; if (Who == 's') { // Kör programmet som server if (Protocol == 't') DoServerTCP(Port); else DoServerUDP(Port); } else { // Kör programmet som klient if (Protocol == 't') DoClientTCP(Port); else DoClientUDP(Port); } // Vänta tills användaren trycker ner 'enter' tangenten std::cout << "Tryck ner ENTER för att avsluta..." << std::endl; std::cin.ignore(10000, '\n'); std::cin.ignore(10000, '\n'); return 0; } //FUNKTIONERNA // ****************************************************** // // Skapa en TCP klient och anslut till en startad server // ****************************************************** // void DoClientTCP(unsigned short Port) { // Fråga efter serverns adress sf::IPAddress ServerAddress; do { std::cout << "Skriv adresss eller namn på servern du vill ansluta till : "; std::cin >> ServerAddress; } while (!ServerAddress.IsValid()); // Skapa en TCP socket för att kommunicera med servern sf::SocketTCP Client; // Anslut till servern if (Client.Connect(Port, ServerAddress) != sf::Socket::Done) return; std::cout << "Ansluten till server " << ServerAddress << std::endl; // Få meddelande från en klient char Message[128]; std::size_t Received; if (Client.Receive(Message, sizeof(Message), Received) != sf::Socket::Done) return; // Visa upp meddelandet std::cout << "Meddelande mottaget från server : \"" << Message << "\"" << std::endl; // Definiera ett meddelande att skicka tillbaka till servern char ToSend[] = "Hej, klient pratar !"; // Skicka meddelandet if (Client.Send(ToSend, sizeof(ToSend)) != sf::Socket::Done) return; std::cout << "Meddelande skickat till server : \"" << ToSend << "\"" << std::endl; // Stäng socketen när vi är klarar Client.Close(); } // ****************************************************** // // Skapa en TCP server och vänta på inkommande meddelanden // ****************************************************** // void DoServerTCP(unsigned short Port) { // Skapa en TCP socket för att kommunicera med klienter sf::SocketTCP Server; // Lyssna på en port för inkommande meddelanden if (!Server.Listen(Port)) return; std::cout << "Servern lyssnar på port " << Port << ", väntar på anslutning... " << std::endl; // Vänta på kontakt sf::IPAddress ClientAddress; sf::SocketTCP Client; Server.Accept(Client, &ClientAddress); std::cout << "Klient ansluten : " << ClientAddress << std::endl; // Skicka ett meddelande till klienten char ToSend[] = "Hej, server meddelar"; if (Client.Send(ToSend, sizeof(ToSend)) != sf::Socket::Done) return; std::cout << "Meddelande skickat till klient : \"" << ToSend << "\"" << std::endl; // Motta meddelande från klienten char Message[128]; std::size_t Received; if (Client.Receive(Message, sizeof(Message), Received) != sf::Socket::Done) return; // Visa meddelandet std::cout << "Meddelande mottaget från klient : \"" << Message << "\"" << std::endl; // Stäng sockets när vi är klara Client.Close(); Server.Close(); } // ************************************************************** // // Skapa en UDP klient och skicka meddelande med UDP till en server // ************************************************************** // void DoClientUDP(unsigned short Port) { // Fråga efter serverns IP-adress sf::IPAddress ServerAddress; do { std::cout << "Skriv in IP-adressen eller namnet på servern du vill skicka ett meddelande till : "; std::cin >> ServerAddress; } while (!ServerAddress.IsValid()); // Skapa en UDP socket för att kunna kommunicera med servern sf::SocketUDP Client; // Skicka ett meddelande till servern char Message[] = "Hej, skickat av klient!"; if (Client.Send(Message, sizeof(Message), ServerAddress, Port) != sf::Socket::Done) return; std::cout << "Meddelande skickat till server : \"" << Message << "\"" << std::endl; // Stäng ner socketen när det är klart Client.Close(); } // ****************************************************** // // Starta en UDP server och vänta på inkommande meddelanden // ****************************************************** // void DoServerUDP(unsigned short Port) { // Skapa en UDP socket för att kommunicera med klienten sf::SocketUDP Server; // Koppla den till en specifik port if (!Server.Bind(Port)) return; // Ta emot ett meddelande från vem som helst sf::IPAddress ClientAddress; unsigned short ClientPort; char Message[128]; std::size_t Received; if (Server.Receive(Message, sizeof(Message), Received, ClientAddress, ClientPort) != sf::Socket::Done) return; // Visa upp det std::cout << "Meddelande mottaget från " << ClientAddress << " från port " << ClientPort << " : \"" << Message << "\"" << std::endl; // Stäng socketen när vi är klara Server.Close(); }
Originalkod hittas här: http://www.sfml-dev.org/tutorials/1.6/network-sockets.php
//Skrotkod här nedanför, skall raderas..............
//Originalkod från SFML hemsida. //Bearbetad för att driva ett enkelt spel och inte bara skicka ett ord fram och tillbaka #include <iostream> #include <SFML/System.hpp> #include <SFML/Graphics.hpp> #include <SFML/Window.hpp> #include <SFML/Network.hpp> #include <vector> // using namespace std; #define SFML_STATIC //Se till så att det inte behövs extra DLL-filer //Skapa den klass som spelarna pojken och kon kommer från class spelare { public: sf::Uint8 ID; //0=pojke, 1=ko sf::Int32 hastighetX; //Hastighet i X-led, kan vara negativ sf::Int32 hastighetY; //Hastighet i Y-led, kan vara negativ sf::Sprite sprite; //Bilden som representerar pojken eller kon }; // Server = styr pojken // Client = styr ko //-------------------------------------------------------------- //Skapa paketen som skall skickas mellan datorerna //-------------------------------------------------------------- sf::Packet &operator <<(sf::Packet &Packet, const spelare &C) { return Packet << C.ID << C.hastighetX << C.hastighetY; } sf::Packet &operator >>(sf::Packet &Packet, spelare &C) { return Packet >> C.ID >> C.hastighetX >> C.hastighetY; } //Funktioner för att köra programmet som en server eller som en klient void RunClient(unsigned short Port); void RunServer(unsigned short Port); void PlayerSend(class spelare &s); void PlayerRecieve( class spelare &s); //--------------------------------------------------------- // Programstart //--------------------------------------------------------- int main (int argc, char **argv) { //Början av programkörningen char Who = 'Z'; //Avgör om man skall vara klient eller server float ElapsedTime = 0.0f; //Skapar en konstant för att hålla hastigheten likvärdig på olika datorer //-------------------------------------------------------- // Visa upp lokal adress, troligen 192.168.x.x eller 10.100.x.x eller 169.254.x.x //------------------------------------------- sf::IPAddress Address1 = sf::IPAddress::GetLocalAddress(); std::string IP1 = Address1.ToString(); std::cout<<"Din egen lokala IP-adress = " << IP1 << std::endl << std::endl; //Skapa paket sf::Packet ToSend;//Paketet skapas för att skicka uppgifter sf::Packet Received; //Paket att ta emot uppgifter skapas //Skapa en port som vi skall använda till vår socket //(portarna < 1024 är reserverade) const unsigned short Port = 2435; // Client eller server ?------------------------------------------------ std::cout << "Vill du vara server ('s') eller en klient ('c') ? "; std::cin >> Who; if (Who == 's') RunServer(Port); //Vänta else RunClient(Port); //Anslut till server //Skapa inte spelfönstret innan anslutning skett sf::RenderWindow App(sf::VideoMode(800, 600, 32), "Test - nätverksspel"); //Skapa en pojke spelare pojke; //pojke blir en kopia av klassen spelare pojke.hastighetX = 0; //grundhastighet, skall multipliceras med ”ElapsedTime ”. pojke.hastighetY = 0; //grundhastighet, skall multipliceras med ”ElapsedTime ”. pojke.ID=0; //Skapa en ko spelare ko; //ko blir en kopia av klassen spelare ko.hastighetX = 0; //grundhastighet, skall multipliceras med ”ElapsedTime ”. ko.hastighetY = 0; //grundhastighet, skall multipliceras med ”ElapsedTime ”. ko.ID=1; //Skapa bildhållarna sf::Image pojkbild; sf::Image kobild; //Ladda in bildfilerna pojkbild.LoadFromFile("boy.png"); kobild.LoadFromFile("cow.png"); //Dela ut bild till ko ko.sprite.SetImage(kobild); ko.sprite.SetPosition(500,500); //Dela ut bild till pojke pojke.sprite.SetImage(pojkbild); pojke.sprite.SetPosition(100,100); while(App.IsOpened()) { //Gameloop ElapsedTime=App.GetFrameTime(); //Skapar en konstant för att hålla hastigheten likvärdig på olika datorer sf::Event Event; while (App.GetEvent(Event)) // Ta hand om händelser { //while 2 if (Event.Type == sf::Event::Closed) //kryssat på [x] symbolen? stäng programmet App.Close(); if (Event.Type == sf::Event::KeyPressed) // En tangent har tryckts ner { //if 1 if (Event.Key.Code == sf::Key::Escape) // ESC tangenten = stäng programmet App.Close(); } //slut if 1 } //slut, while 2 if (Who == 's') { //Du är en server //X-led värden if (App.GetInput().IsKeyDown(sf::Key::Left)) { pojke.hastighetX= -100; PlayerSend(pojke); //Skicka ut var pojken är } if (App.GetInput().IsKeyDown(sf::Key::Right)) { pojke.hastighetX= 100; PlayerSend(pojke); //Skicka ut var pojken är } //Spring ingenstans om inte knapparna är nedtryckta if (!App.GetInput().IsKeyDown(sf::Key::Left) && !App.GetInput().IsKeyDown(sf::Key::Right)) { pojke.hastighetX= 0; PlayerSend(pojke); //Skicka ut var pojken är } if (App.GetInput().IsKeyDown(sf::Key::Up)) { pojke.hastighetY= -100; PlayerSend(pojke); //Skicka ut var pojken är } if (App.GetInput().IsKeyDown(sf::Key::Down)) { pojke.hastighetY= 100; PlayerSend(pojke); //Skicka ut var pojken är } //Spring ingenstans om inte knapparna är nedtryckta if (!App.GetInput().IsKeyDown(sf::Key::Up) && !App.GetInput().IsKeyDown(sf::Key::Down)) { pojke.hastighetY= 0; PlayerSend(pojke); //Skicka ut var pojken är } PlayerRecieve(ko); } //Du är en server if ( Who != 's') { //Du är en klient //X-led värden if (App.GetInput().IsKeyDown(sf::Key::Left)) { ko.hastighetX= -100; PlayerSend(ko); //Skicka ut var kon är } if (App.GetInput().IsKeyDown(sf::Key::Right)) { ko.hastighetX= 100; PlayerSend(ko); //Skicka ut var kon är } //Spring ingenstans om inte knapparna är nedtryckta if (!App.GetInput().IsKeyDown(sf::Key::Left) && !App.GetInput().IsKeyDown(sf::Key::Right)) { ko.hastighetX= 0; PlayerSend(ko); //Skicka ut var kon är } if (App.GetInput().IsKeyDown(sf::Key::Up)) { ko.hastighetY= -100; PlayerSend(ko); //Skicka ut var kon är } if (App.GetInput().IsKeyDown(sf::Key::Down)) { ko.hastighetY= 100; PlayerSend(ko); //Skicka ut var kon är } //Spring ingenstans om inte knapparna är nedtryckta if (!App.GetInput().IsKeyDown(sf::Key::Up) && !App.GetInput().IsKeyDown(sf::Key::Down)) { ko.hastighetY= 0; PlayerSend(ko); //Skicka ut var kon är } PlayerRecieve(pojke); } //Du är en klient //Flytta spelpjäserna pojke.sprite.Move(pojke.hastighetX * ElapsedTime,pojke.hastighetY * ElapsedTime); ko.sprite.Move(ko.hastighetX * ElapsedTime,ko.hastighetY* ElapsedTime); //Rita ut ändringarna på skärmen App.Clear(); App.Draw(pojke.sprite); App.Draw(ko.sprite); App.Display(); } //Gameloop return 0; } //slut på programkörningen void RunClient(unsigned short Port) { // Fråga efter serveradressen sf::IPAddress ServerAddress; do { std::cout << "Skriv in IP adress eller namn att ansluta till : "; std::cin >> ServerAddress; } while (!ServerAddress.IsValid()); // Skapa en TCP socket för att samarbeta med servern sf::SocketTCP Client; // Anslut till servern if (Client.Connect(Port, ServerAddress) != sf::Socket::Done) return; std::cout << "Ansluten till server " << ServerAddress << std::endl; } //Serverfunktionerna void RunServer(unsigned short Port) { // Skapa en TCP socket för att kommunicera med klienterna sf::SocketTCP Server; // Lyssna på en port för inkommande anrop if (!Server.Listen(Port)) return; std::cout << "Servern lyssnar på port " << Port << ", väntar på anslutning... " << std::endl; // Väntar på kontakt sf::IPAddress ClientAddress; sf::SocketTCP Client; Server.Accept(Client, &ClientAddress); std::cout << "Klient ansluten : " << ClientAddress << std::endl; } //Skicka iväg informationen om spelaren till mottagaren void PlayerSend(class spelare &s) { spelare C = {s.ID, s.hastighetX, s.hastighetY}; sf::Packet RegularPacket; //Paket skapas med tre variabler sf::SocketTCP Client; //Socket skapas RegularPacket << C; //Paketet tilldelas de tre variablerna if (C.ID == 0) {std::cout << "Pojke skickad till klienten: " << std::endl;} else {std::cout << "Ko skickad till klienten: " << std::endl;} if (Client.Send(RegularPacket) != sf::Socket::Done) //Paketet skickas return; } void PlayerRecieve(class spelare &s) { sf::Packet RegularPacket; //Paket skapas med tre variabler sf::SocketTCP Client; //Client.SetBlocking(false); //Tar emot utan avbrott spelare C; if (Client.Receive(RegularPacket) != sf::Socket::Done) return; std::cout<<"Tar emot..."<< std::endl; //test if (RegularPacket >> C) { if (C.ID == 0) {std::cout << "Pojke mottagen från servern: " << std::endl;} else {std::cout << "Ko mottagen från servern: " << std::endl;} } else {std::cout << "Ingenting mottaget från servern: " << std::endl;} //std::cout << s.ID << " ID, " << s.hastighetX << " hastighet x, " << s.hastighetY << " hastighet y" << std::endl; }