Hoppa till innehållet

Programmera spel i C++ för nybörjare/Nätverksprogrammering 1

Från Wikibooks


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;
	
 }