lsalzman / enet

ENet reliable UDP networking library
MIT License
2.71k stars 669 forks source link

Trying to figure out how to make a basic echo server #170

Closed UnidayStudio closed 3 years ago

UnidayStudio commented 3 years ago

I've been trying to figure out enet for some days now, reading the tutorial, but I'm having a hard time trying to get it working.

I'm trying to make a basic echo stuff, in a single file, just to see if I'm able to create a server, connect to it and send a message, nothing fancy. It's not working.

I'll leave all the code bellow. For your information, I'm having no errors or exception. It simply doesn't Log anything in the console... from my understanding, it was supposed to log that the client connected at least (or return a NULL peer, I guess?)

Initialization:

if (enet_initialize() != 0) {
    throw std::exception("Enet failed to init ENet.");
}

// Server address:
ENetAddress address;
address.host = ENET_HOST_ANY;
address.port = 1234;

// Server:
m_server = enet_host_create(&address, 32, 2, 0, 0);
if (m_server == NULL) {
    Log("Error: Falied to create server.");
}

// Client:
m_client = enet_host_create(NULL, 1, 2, 0, 0);
if (m_client == NULL) {
    Log("Error: Falied to create client.");
}

// Connecting to the server:
m_clientPeer = enet_host_connect((ENetHost*)m_client, &address, 2, 0);
if (m_clientPeer == NULL) {
    Log("Error: Falied to connect to server.");
}

in the Gameloop...

ENetHost* server = (ENetHost*)m_server;
ENetHost* client = (ENetHost*)m_client;

// an UI button on my interface to send a message...
if (ui::Button("Send a test message")) {
    ENetPacket * packet = enet_packet_create("packet",
        strlen("packet") + 1,
        ENET_PACKET_FLAG_RELIABLE);
    enet_peer_send((ENetPeer*)m_clientPeer, 0, packet);
}

// Handle the Server inputs
{
    ENetEvent event;
    while (enet_host_service(server, &event, 0) > 0) {
        if (event.type == ENET_EVENT_TYPE_CONNECT) {
            Log("Server: A new client connected!");
        }
        else if (event.type == ENET_EVENT_TYPE_RECEIVE) {   
            // Echo:
            ENetPacket * packet = enet_packet_create(
                event.packet->data, event.packet->dataLength,
                ENET_PACKET_FLAG_RELIABLE
            );
            enet_peer_send((ENetPeer*)event.peer, 0, packet);

            Log("Server: New client message!");
        }
        else if (event.type == ENET_EVENT_TYPE_DISCONNECT) {
            Log("Server: A client disconnected!");
        }
    }
}

// Handle the Client inputs
{
    ENetEvent event;
    while (enet_host_service(client, &event, 0) > 0) {
        if (event.type == ENET_EVENT_TYPE_CONNECT) {
            Log("Client: A new client connected!");
        }
        else if (event.type == ENET_EVENT_TYPE_RECEIVE) {
            Log("Client: New client message!");
        }
        else if (event.type == ENET_EVENT_TYPE_DISCONNECT) {
            Log("Client: A client disconnected!");
        }
    }
}

Shutdown

if (m_clientPeer) {
    enet_peer_disconnect((ENetPeer*)m_clientPeer, 0);
}

if (m_client) {
    enet_host_destroy((ENetHost*)m_client);
}

if (m_server) {
    enet_host_destroy((ENetHost*)m_server);
}

enet_deinitialize();
lsalzman commented 3 years ago

That won't work as you have written it. It's best to think of the connection handshake of having an indeterminate amount of interleaved stages, so if you only service the server, then the client, then exit, the handshake for the connection will never have the opportunity to finish. It may take multiple passes of servicing server and client for things to settle.

UnidayStudio commented 3 years ago

That won't work as you have written it. It's best to think of the connection handshake of having an indeterminate amount of interleaved stages, so if you only service the server, then the client, then exit, the handshake for the connection will never have the opportunity to finish. It may take multiple passes of servicing server and client for things to settle.

Could you provide a "hello, world" example? I'm just trying to figure out how to get the basics working. Thank you!

UnidayStudio commented 3 years ago

Quick update (for those who had the same problem):

I've managed to figure out how to fix my code by looking for some python enet examples (pyenet). I realized that my code was missing the enet_address_set_host(&address, "localhost"); in the initialization, right here:

// Server address:
ENetAddress address;
address.host = ENET_HOST_ANY;
address.port = 1234;

enet_address_set_host(&address, "localhost");

Now it works as expected. :)