From 881de6c14ece7ef1e463f23311d39042e6a4a197 Mon Sep 17 00:00:00 2001 From: zhuyie Date: Wed, 21 Feb 2018 20:51:52 +0800 Subject: [PATCH 1/4] Add examples --- CMakeLists.txt | 6 +++ examples/client.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++ examples/server.c | 99 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 223 insertions(+) create mode 100644 examples/client.c create mode 100644 examples/server.c diff --git a/CMakeLists.txt b/CMakeLists.txt index d3d4aa8d..72f61ef6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,3 +92,9 @@ add_library(enet STATIC if (MINGW) target_link_libraries(enet winmm ws2_32) endif() + +add_executable(server examples/server.c) +target_link_libraries(server enet) + +add_executable(client examples/client.c) +target_link_libraries(client enet) diff --git a/examples/client.c b/examples/client.c new file mode 100644 index 00000000..4e3e8593 --- /dev/null +++ b/examples/client.c @@ -0,0 +1,118 @@ +#include +#include + +int main(int argc, char** argv) +{ + ENetHost *client = NULL; + ENetAddress address; + ENetEvent event; + ENetPeer *peer; + ENetPacket *packet; + int retcode; + + if (enet_initialize() != 0) + { + fprintf(stderr, "An error occurred while initializing ENet.\n"); + return 1; + } + + 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 */, + 0 /* assume any amount of incoming bandwidth */, + 0 /* assume any amount of outgoing bandwidth */); + if (client == NULL) + { + fprintf(stderr, "An error occurred while trying to create an ENet client host.\n"); + goto Exit; + } + + /* Initiate the connection. */ + enet_address_set_host(&address, "localhost"); + address.port = 1234; + peer = enet_host_connect(client /* host seeking the connection */, + &address /* destination for the connection */, + 2 /* number of channels to allocate */, + 0 /* user data supplied to the receiving host */); + if (peer == NULL) + { + fprintf(stderr, "No available peers for initiating an ENet connection.\n"); + goto Exit; + } + + /* Wait up to 5 seconds for the connection attempt to succeed. */ + if (enet_host_service(client, &event, 5000) > 0 && event.type == ENET_EVENT_TYPE_CONNECT) + { + fprintf(stdout, "Connect succeeded.\n"); + } + 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); + + fprintf(stderr, "Connect failed.\n"); + goto Exit; + } + + /* Sending packets to an ENet peer. */ + for (int i = 0; i < 4; i++) + { + packet = enet_packet_create(NULL /* initial contents of the packet's data */, + 9 /* size of the data allocated for this packet */, + ENET_PACKET_FLAG_RELIABLE /* flags for this packet */); + + sprintf((char*)packet->data, "packet %d", i); + + enet_peer_send(peer /* destination for the packet */, + i % 2 /* channel on which to send */, + packet /* packet to send */); + } + /* Send out queued packets. One could just use enet_host_service() instead. */ + enet_host_flush(client); + + /* Initiate the disconnection. */ + enet_peer_disconnect(peer /* peer to request a disconnection */, + 0 /* data describing the disconnection */); + + /* Allow up to 3 seconds for the disconnect to succeed and drop any packets received packets. */ + retcode = 1; + while (retcode > 0) + { + retcode = enet_host_service(client, &event, 3000); + if (retcode > 0) + { + switch (event.type) + { + case ENET_EVENT_TYPE_RECEIVE: + enet_packet_destroy(event.packet); + break; + + case ENET_EVENT_TYPE_DISCONNECT: + fprintf(stdout, "Disconnect succeeded.\n"); + retcode = 0; + break; + + default: + ; + } + } + else + { + /* Timeout or failure */ + fprintf(stderr, "Disconnect failed.\n"); + enet_peer_reset(peer); + } + } + +Exit: + if (client != NULL) + { + enet_host_destroy(client); + } + enet_deinitialize(); + + return 0; +} + diff --git a/examples/server.c b/examples/server.c new file mode 100644 index 00000000..0141752c --- /dev/null +++ b/examples/server.c @@ -0,0 +1,99 @@ +#include +#include +#include + +int main(int argc, char **argv) +{ + int retcode; + ENetAddress address; + ENetHost *server = NULL; + ENetEvent event; + char peerIP[30]; + + if (enet_initialize() != 0) + { + fprintf(stderr, "An error occurred while initializing ENet.\n"); + return 1; + } + + address.host = ENET_HOST_ANY; + address.port = 1234; + 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 */); + if (server == NULL) + { + fprintf(stderr, "An error occurred while trying to create an ENet server host.\n"); + goto Exit; + } + + fprintf(stdout, "Server started\n"); + + for (;;) + { + retcode = enet_host_service(server, /* host to service */ + &event, /* an event structure where event details will be placed if one occurs */ + 1000 /* number of milliseconds that ENet should wait for events */); + if (retcode > 0) + { + /* an event occurred within the specified time limit */ + if (enet_address_get_host_ip(&(event.peer->address), peerIP, 30) != 0) + { + strcpy(peerIP, "?"); + } + switch (event.type) + { + case ENET_EVENT_TYPE_CONNECT: + fprintf(stdout, + "Client connected: %s:%u\n", + peerIP, + (unsigned int)event.peer->address.port); + break; + + case ENET_EVENT_TYPE_RECEIVE: + fprintf(stdout, + "Packet received: %s:%u channel=%u length=%u data=\"%s\"\n", + peerIP, + (unsigned int)event.peer->address.port, + event.channelID, + (unsigned int)event.packet->dataLength, + (const char*)event.packet->data); + /* Clean up the packet now that we're done using it. */ + enet_packet_destroy(event.packet); + break; + + case ENET_EVENT_TYPE_DISCONNECT: + fprintf(stdout, + "Client disconnected: %s:%u\n", + peerIP, + (unsigned int)event.peer->address.port); + break; + + default: + fprintf(stderr, "Should never be reached"); + } + } + else if (retcode < 0) + { + /* failure */ + fprintf(stderr, "An error occurred while waiting for events.\n"); + break; + } + else + { + /* no event occurred */ + } + } + +Exit: + if (server != NULL) + { + enet_host_destroy(server); + } + enet_deinitialize(); + + return 0; +} + From 034fb607b05786b986bdd7206415488ffab0da28 Mon Sep 17 00:00:00 2001 From: zhuyie Date: Wed, 21 Feb 2018 21:13:34 +0800 Subject: [PATCH 2/4] Fix MSVC link errors --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 72f61ef6..c2d057ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,7 +89,7 @@ add_library(enet STATIC ${SOURCE_FILES} ) -if (MINGW) +if (WIN32 OR MINGW) target_link_libraries(enet winmm ws2_32) endif() From a190865856b575f6c3d3a2cc10faa53f18a9f3b6 Mon Sep 17 00:00:00 2001 From: zhuyie Date: Thu, 22 Feb 2018 14:08:06 +0800 Subject: [PATCH 3/4] Add command line options --- examples/client.c | 111 ++++++++++++++++++++++++++++++++++++++-------- examples/server.c | 63 ++++++++++++++++++++------ 2 files changed, 143 insertions(+), 31 deletions(-) diff --git a/examples/client.c b/examples/client.c index 4e3e8593..ddf395a7 100644 --- a/examples/client.c +++ b/examples/client.c @@ -1,4 +1,5 @@ #include +#include #include int main(int argc, char** argv) @@ -9,6 +10,52 @@ int main(int argc, char** argv) ENetPeer *peer; ENetPacket *packet; int retcode; + unsigned int time_begin; + const char *host = "localhost"; + unsigned short port = 1234; + int verbose = 0; + int packet_count = 10; + int packet_length = 100; + + for (int i = 1; i < argc; i++) + { + if (strcmp(argv[i], "-h") == 0) + { + if (i + 1 < argc) + { + host = argv[i+1]; + } + i++; + } + else if (strcmp(argv[i], "-p") == 0) + { + if (i + 1 < argc) + { + port = (unsigned short)atoi(argv[i+1]); + } + i++; + } + else if (strcmp(argv[i], "-v") == 0) + { + verbose = 1; + } + else if (strcmp(argv[i], "-c") == 0) + { + if (i + 1 < argc) + { + packet_count = atoi(argv[i+1]); + } + i++; + } + else if (strcmp(argv[i], "-l") == 0) + { + if (i + 1 < argc) + { + packet_length = atoi(argv[i+1]); + } + i++; + } + } if (enet_initialize() != 0) { @@ -28,8 +75,8 @@ int main(int argc, char** argv) } /* Initiate the connection. */ - enet_address_set_host(&address, "localhost"); - address.port = 1234; + enet_address_set_host(&address, host); + address.port = port; peer = enet_host_connect(client /* host seeking the connection */, &address /* destination for the connection */, 2 /* number of channels to allocate */, @@ -43,7 +90,7 @@ int main(int argc, char** argv) /* Wait up to 5 seconds for the connection attempt to succeed. */ if (enet_host_service(client, &event, 5000) > 0 && event.type == ENET_EVENT_TYPE_CONNECT) { - fprintf(stdout, "Connect succeeded.\n"); + fprintf(stdout, "Connect succeeded\n"); } else { @@ -52,29 +99,57 @@ int main(int argc, char** argv) /* had run out without any significant event. */ enet_peer_reset(peer); - fprintf(stderr, "Connect failed.\n"); + fprintf(stderr, "Connect failed\n"); goto Exit; } - /* Sending packets to an ENet peer. */ - for (int i = 0; i < 4; i++) + /* Ping-Pong */ + time_begin = enet_time_get(); + for (int i = 0; i < packet_count; i++) { - packet = enet_packet_create(NULL /* initial contents of the packet's data */, - 9 /* size of the data allocated for this packet */, + packet = enet_packet_create(NULL /* initial contents of the packet's data */, + packet_length /* size of the data allocated for this packet */, ENET_PACKET_FLAG_RELIABLE /* flags for this packet */); - + memset(packet->data, 0, packet_length); sprintf((char*)packet->data, "packet %d", i); - - enet_peer_send(peer /* destination for the packet */, - i % 2 /* channel on which to send */, + enet_peer_send(peer /* destination for the packet */, + i % 2 /* channel on which to send */, packet /* packet to send */); + + retcode = enet_host_service(client /* host to service */, + &event /* an event structure where event details will be placed if one occurs */, + 1000 /* number of milliseconds that ENet should wait for events */); + if (retcode > 0 && event.type == ENET_EVENT_TYPE_RECEIVE) + { + if (verbose) + { + fprintf(stdout, + "Reply packet %d: channel=%u length=%u data=\"%s\"\n", + i, + event.channelID, + (unsigned int)event.packet->dataLength, + (const char*)event.packet->data); + } + /* Clean up the packet now that we're done using it. */ + enet_packet_destroy(event.packet); + } + else + { + /* Something is wrong. */ + fprintf(stderr, "Lost reply packet %d\n", i); + } } - /* Send out queued packets. One could just use enet_host_service() instead. */ - enet_host_flush(client); + fprintf(stdout, "PacketCount=%d Time=%u\n", packet_count, enet_time_get() - time_begin); + + /* Send a large packet(should be fragmented). */ + packet = enet_packet_create(NULL, 6666, ENET_PACKET_FLAG_RELIABLE); + memset(packet->data, 0, 6666); + strcpy((char*)packet->data, "This is a large packet..."); + enet_peer_send(peer, 0, packet); /* Initiate the disconnection. */ - enet_peer_disconnect(peer /* peer to request a disconnection */, - 0 /* data describing the disconnection */); + enet_peer_disconnect_later(peer /* peer to request a disconnection */, + 0 /* data describing the disconnection */); /* Allow up to 3 seconds for the disconnect to succeed and drop any packets received packets. */ retcode = 1; @@ -90,7 +165,7 @@ int main(int argc, char** argv) break; case ENET_EVENT_TYPE_DISCONNECT: - fprintf(stdout, "Disconnect succeeded.\n"); + fprintf(stdout, "Disconnect succeeded\n"); retcode = 0; break; @@ -101,7 +176,7 @@ int main(int argc, char** argv) else { /* Timeout or failure */ - fprintf(stderr, "Disconnect failed.\n"); + fprintf(stderr, "Disconnect failed\n"); enet_peer_reset(peer); } } diff --git a/examples/server.c b/examples/server.c index 0141752c..4a8ab309 100644 --- a/examples/server.c +++ b/examples/server.c @@ -2,13 +2,28 @@ #include #include +typedef struct Client +{ + char ip[16]; + unsigned short port; + unsigned int packet_count; +} Client; + int main(int argc, char **argv) { int retcode; ENetAddress address; ENetHost *server = NULL; ENetEvent event; - char peerIP[30]; + Client *client; + ENetPacket *packet; + int verbose = 0; + + if (argc > 1) + { + if (strcmp(argv[1], "-v") == 0) + verbose = 1; + } if (enet_initialize() != 0) { @@ -39,36 +54,58 @@ int main(int argc, char **argv) if (retcode > 0) { /* an event occurred within the specified time limit */ - if (enet_address_get_host_ip(&(event.peer->address), peerIP, 30) != 0) - { - strcpy(peerIP, "?"); - } switch (event.type) { case ENET_EVENT_TYPE_CONNECT: + /* Create a client */ + client = (Client*)calloc(1, sizeof(Client)); + client->ip[0] = '?'; + enet_address_get_host_ip(&(event.peer->address), client->ip, sizeof(client->ip)); + client->port = event.peer->address.port; + /* Save the Client* in peer->data */ + event.peer->data = client; fprintf(stdout, "Client connected: %s:%u\n", - peerIP, - (unsigned int)event.peer->address.port); + client->ip, + (unsigned int)client->port); break; case ENET_EVENT_TYPE_RECEIVE: - fprintf(stdout, + /* Get the Client* */ + client = (Client*)event.peer->data; + if (verbose) + { + fprintf(stdout, "Packet received: %s:%u channel=%u length=%u data=\"%s\"\n", - peerIP, - (unsigned int)event.peer->address.port, + client->ip, + (unsigned int)client->port, event.channelID, (unsigned int)event.packet->dataLength, (const char*)event.packet->data); + } + /* Update packet_count */ + client->packet_count++; /* Clean up the packet now that we're done using it. */ enet_packet_destroy(event.packet); + /* Create a new packet. */ + packet = enet_packet_create(NULL, 50, ENET_PACKET_FLAG_RELIABLE); + memset(packet->data, 0, 50); + sprintf((char*)packet->data, "Hi, I have got the packet %u.", client->packet_count - 1); + /* Send it back. */ + enet_peer_send(event.peer, event.channelID, packet); break; case ENET_EVENT_TYPE_DISCONNECT: + /* Get the Client* */ + client = (Client*)event.peer->data; fprintf(stdout, - "Client disconnected: %s:%u\n", - peerIP, - (unsigned int)event.peer->address.port); + "Client disconnected: %s:%u packet_count=%u\n", + client->ip, + (unsigned int)client->port, + client->packet_count); + /* Destroy the client */ + event.peer->data = NULL; + free(client); break; default: From 9e280476fa167c0df73bf8ea9a068335d915311b Mon Sep 17 00:00:00 2001 From: zhuyie Date: Tue, 31 Mar 2020 10:04:58 +0800 Subject: [PATCH 4/4] Add a CMake option for building examples --- CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index c2d057ac..5ee0dc31 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 2.6) project(enet) +option(BUILD_EXAMPLES "Build examples" OFF) + # The "configure" step. include(CheckFunctionExists) include(CheckStructHasMember) @@ -93,8 +95,13 @@ if (WIN32 OR MINGW) target_link_libraries(enet winmm ws2_32) endif() +if (BUILD_EXAMPLES) + add_executable(server examples/server.c) target_link_libraries(server enet) add_executable(client examples/client.c) target_link_libraries(client enet) + +endif() +