2012-05-09 7 views
6

Nie zamierzam używać boost :: asio, jest to zbyt skomplikowane dla moich potrzeb.Biblioteka taka jak ENet, ale dla TCP?

Buduję grę na platformę, na komputery, iPhone i Androida.

Znalazłem bibliotekę o nazwie ENet, która jest prawie tym, czego potrzebuję, ale używa UDP, która nie obsługuje szyfrowania i kilku innych rzeczy. Biorąc pod uwagę, że gra to gra karciana sterowana zdarzeniami, TCP wydaje się pasować.

Jednak znalazłem tylko gniazda WINSOCK/berkley i bost :: asio.

Oto przykład aplikacji klient-serwer z ENet:

#include <enet/enet.h> 
#include <stdlib.h> 
#include <string> 
#include <iostream> 

class Host 
{ 
    ENetAddress address; 
    ENetHost * server; 
    ENetHost* client; 
    ENetEvent event; 
public: 
    Host() 
     :server(NULL) 
    { 
     enet_initialize(); 
     setupServer(); 
    } 

    void setupServer() 
    { 
     if(server) 
     { 
      enet_host_destroy(server); 
      server = NULL; 
     } 

     address.host = ENET_HOST_ANY; 
     /* Bind the server to port 1234. */ 
     address.port = 1721; 

     server = enet_host_create (& address /* the address to bind the server host to */, 
      32  /* allow up to 32 clients and/or outgoing connections */, 
      2  /* allow up to 2 channels to be used, 0 and 1 */, 
      0  /* assume any amount of incoming bandwidth */, 
      0  /* assume any amount of outgoing bandwidth */); 

    } 

    void daLoop() 
    { 
     while(true) 
     { 
      /* Wait up to 1000 milliseconds for an event. */ 
      while (enet_host_service (server, & event, 5000) > 0) 
      { 
       ENetPacket * packet; 

       switch (event.type) 
       { 
       case ENET_EVENT_TYPE_CONNECT: 
        printf ("A new client connected from %x:%u.\n", 
         event.peer -> address.host, 
         event.peer -> address.port); 

        /* Store any relevant client information here. */ 
        event.peer -> data = "Client information"; 

        /* Create a reliable packet of size 7 containing "packet\0" */ 
        packet = enet_packet_create ("packet", 
         strlen ("packet") + 1, 
         ENET_PACKET_FLAG_RELIABLE); 

        /* Extend the packet so and append the string "foo", so it now */ 
        /* contains "packetfoo\0"          */ 
        enet_packet_resize (packet, strlen ("packetfoo") + 1); 
        strcpy ((char*)& packet -> data [strlen ("packet")], "foo"); 

        /* Send the packet to the peer over channel id 0. */ 
        /* One could also broadcast the packet by   */ 
        /* enet_host_broadcast (host, 0, packet);   */ 
        enet_peer_send (event.peer, 0, packet); 
        /* One could just use enet_host_service() instead. */ 
        enet_host_flush (server); 

        break; 

       case ENET_EVENT_TYPE_RECEIVE: 
        printf ("A packet of length %u containing %s was received from %s on channel %u.\n", 
         event.packet -> dataLength, 
         event.packet -> data, 
         event.peer -> data, 
         event.channelID); 

        /* Clean up the packet now that we're done using it. */ 
        enet_packet_destroy (event.packet); 

        break; 

       case ENET_EVENT_TYPE_DISCONNECT: 
        printf ("%s disconected.\n", event.peer -> data); 

        /* Reset the peer's client information. */ 

        event.peer -> data = NULL; 
       } 
      } 
     } 

    } 

     ~Host() 
    { 
     if(server) 
     { 
      enet_host_destroy(server); 
      server = NULL; 
     } 

     atexit (enet_deinitialize); 
    } 
}; 

class Client 
{ 
    ENetAddress address; 
    ENetEvent event; 
    ENetPeer *peer; 
    ENetHost* client; 
public: 
    Client() 
     :peer(NULL) 
    { 
     enet_initialize(); 
     setupPeer(); 
    } 

    void setupPeer() 
    { 

     client = enet_host_create (NULL /* create a client host */, 
      1 /* only allow 1 outgoing connection */, 
      2 /* allow up 2 channels to be used, 0 and 1 */, 
      57600/8 /* 56K modem with 56 Kbps downstream bandwidth */, 
      14400/8 /* 56K modem with 14 Kbps upstream bandwidth */); 

     if (client == NULL) 
     { 
      fprintf (stderr, 
       "An error occurred while trying to create an ENet client host.\n"); 
      exit (EXIT_FAILURE); 
     } 

     /* Connect to some.server.net:1234. */ 
     enet_address_set_host (& address, "192.168.2.13"); 
     address.port = 1721; 

     /* Initiate the connection, allocating the two channels 0 and 1. */ 
     peer = enet_host_connect (client, & address, 2, 0);  

     if (peer == NULL) 
     { 
      fprintf (stderr, 
       "No available peers for initiating an ENet connection.\n"); 
      exit (EXIT_FAILURE); 
     } 

     /* Wait up to 5 seconds for the connection attempt to succeed. */ 
     if (enet_host_service (client, & event, 20000) > 0 && 
      event.type == ENET_EVENT_TYPE_CONNECT) 
     { 
      std::cout << "Connection to some.server.net:1234 succeeded." << std::endl; 
     } 
     else 
     { 
      /* Either the 5 seconds are up or a disconnect event was */ 
      /* received. Reset the peer in the event the 5 seconds */ 
      /* had run out without any significant event.   */ 
      enet_peer_reset (peer); 

      puts ("Connection to some.server.net:1234 failed."); 
     } 
    } 


    void daLoop() 
    { 
     ENetPacket* packet; 

     /* Create a reliable packet of size 7 containing "packet\0" */ 
     packet = enet_packet_create ("backet", 
      strlen ("backet") + 1, 
      ENET_PACKET_FLAG_RELIABLE); 

     /* Extend the packet so and append the string "foo", so it now */ 
     /* contains "packetfoo\0"          */ 
     enet_packet_resize (packet, strlen ("backetfoo") + 1); 
     strcpy ((char*)& packet -> data [strlen ("backet")], "foo"); 

     /* Send the packet to the peer over channel id 0. */ 
     /* One could also broadcast the packet by   */ 
     /* enet_host_broadcast (host, 0, packet);   */ 
     enet_peer_send (event.peer, 0, packet); 
     /* One could just use enet_host_service() instead. */ 
     enet_host_flush (client); 

     while(true) 
     { 
      /* Wait up to 1000 milliseconds for an event. */ 
      while (enet_host_service (client, & event, 1000) > 0) 
      { 
       ENetPacket * packet; 

       switch (event.type) 
       { 
       case ENET_EVENT_TYPE_RECEIVE: 
        printf ("A packet of length %u containing %s was received from %s on channel %u.\n", 
         event.packet -> dataLength, 
         event.packet -> data, 
         event.peer -> data, 
         event.channelID); 

        /* Clean up the packet now that we're done using it. */ 
        enet_packet_destroy (event.packet); 

        break; 
       } 
      } 
     } 
    } 
    ~Client() 
    { 
     atexit (enet_deinitialize); 
    } 
}; 

int main() 
{ 
    std::string a; 
    std::cin >> a; 
    if(a == "host") 
    { 
     Host host; 
     host.daLoop(); 
    } 
    else 
    { 
     Client c; 
     c.daLoop(); 
    } 

    return 0; 
} 

Spojrzałem na niektórych samouczków gniazdowych i wydawało się nieco zbyt niskim poziomie.

Po prostu potrzebuję czegoś, co usuwa platformę (np. Bez WINSOCKS) i ma podstawową zdolność do śledzenia połączonych klientów i wysyłania im wiadomości.

Dzięki

Odpowiedz

5

Późne odpowiedź, ale być może to pomoże ktoś inny.

Szyfrowanie to funkcja wysokiego poziomu. Sam TCP ani UDP nie obsługuje szyfrowania. Oba są protokołami niskiego poziomu. Właściwie możemy powiedzieć, że TCP jest protokołem wyższego poziomu w porównaniu do protokołu UDP, ponieważ protokół TCP zawiera kilka zaawansowanych funkcji, które mogą być przydatne ... lub nie, w zależności od projektu, w którym będzie używany.

ENet jest dobry, ponieważ zapewnia korzyści obu światów - niezawodność protokołu TCP oraz wolność i niewielką wagę UDP. Nie ma nic złego w tym, że ENET używa wewnętrznie tylko UDP, a nie TCP, ponieważ ENet jest w stanie zapewnić prawie wszystko, co robi TCP, i wiele więcej.

Jeśli chcesz mieć szyfrowanie, musisz dodać go samodzielnie, bez względu na to, czy wybrałeś TCP, UDP, czy ENET. Sugeruję więc, abyś nadal korzystał z ENET, jeśli czujesz się z nim komfortowo, a kiedy uruchomisz grę, możesz dodać dowolny algorytm szyfrowania, o ile wybierzesz ten sam algorytm dla klienta i serwera. Możesz wybrać bibliotekę szyfrowania innej firmy i po prostu przekazać pakiety sieciowe za jej pośrednictwem. ENET nie dba o to, jakie dane są przez nią przesyłane.

Może Poniższy artykuł pomoże z ENet:

Network Programming with ENet By Mike Diehl

a także zapoznać się z poniższym Stackoverflow tematu na temat szyfrowania dla małych pakietów sieciowych:

Best practices for encrypting continuous/small UDP data

0

I heard Mordor ma warstwę SSL, którą można wykorzystać do szyfrowania sieci.