ENet reliable UDP networking library

Overview
Please visit the ENet homepage at http://enet.bespin.org for installation
and usage instructions.

If you obtained this package from github, the quick description on how to build
is:

# Generate the build system.

autoreconf -vfi

# Compile and install the library.

./configure && make && make install


Comments
  • How do I use SOCKS protocol in enet?

    How do I use SOCKS protocol in enet?

    Hello!

    I have been playing around with SOCKS protocol lately, and I was wondering how do you use SOCKS protocol in enet? Does it require custom logic for data receiving and sending?

    Best regards: Olli.

    opened by GitOlli 12
  • Possible bug in transmission logic of fragmented packets

    Possible bug in transmission logic of fragmented packets

    I've noticed a suspicious behavior when unreliable packets that exceed MTU (without using any packet flags) prevent sending of unreliable packets that below MTU. For example:

    1. Sending and receiving packets continuously every 15 milliseconds in the loop.
    2. Creating and enqueuing for sending an unreliable packet with 64 bytes in size.
    3. Creating and enqueuing for sending an unreliable packet with 2048 bytes in size.
    4. Invoking service or flushing the host.
    5. The packet that exceeded MTU delivered successfully, but the packet below MTU is most likely not (with ~90% of probability).

    It happens on localhost and on remote connections. Packets that exceed MTU and flagged as ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT makes this a non-issue.

    It also happens when packets that exceed MTU are flagged as reliable.

    opened by Zerolean 11
  • enet crashing upon sending packets

    enet crashing upon sending packets

    Hello, so i was wandering when enet crashes. When i create packets with c++, it works. (by creating packets, i mean copying data/adding new data to a byte array). Then i create an ENet packet, then send it which works.

    But when i do the same functions on nodejs, it crashes. I pass the created packet to the c++ addon, then create an enet packet, then after sending, it crashes. Any reason why?

    04 00 00 00 01 00 00 00 ff ff ff ff 00 00 00 00 08 00 00 00 00 00 00 00 00 00 00
     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0
    0 00 00 00 00 00 00 02 00 02 10 00 00 00 4f 6e 43 6f 6e 73 6f 6c 65 4d 65 73 73
    61 67 65 01 02 07 00 00 00 54 65 73 74 69 6e 67 00
    

    this is the bytes of the packet being sent. c++ & nodejs outputs the both though

    opened by Syn9673 10
  • Enet Send and recieve in two threads will crash

    Enet Send and recieve in two threads will crash

    I encapsulated the sending and receiving of Enet, the receiving function will be called in a thread all the time, and the sending will be called in other threads, so there will be a segmentation error. my part of code is as follows. I now want know mybe I cannot understand the Enet library ? for this case ,if one why to fix to use mutex lock ?

    typedef struct _ASD_RELIABLE_UDP { ENetHost *host; ENetPeer *peer; }ASD_RELIABLE_UDP;

    init function: int asd_reliable_udp_init(ASD_RELIABLE_UDP *udp, enet_uint32 sockfd, enet_uint8 *ip, enet_uint16 port) { ENetEvent event; int retry = 0; if(enet_initialize()) { return -1; } //memset(&(udp->event), 0, sizeof(udp->event)); pthread_mutex_init(&(udp->hmutex),NULL);

    if (NULL == ip && 0 != port)
    {
    	ENetAddress address;
    	address.host=ENET_HOST_ANY;
    	address.port=port;
    
    	udp->host = enet_host_create(&address, sockfd, 1, 0,0,0);/*init server*/
    	
    	//udp->host->checksum = asd_check_buffer_sums;
    	printf("==== rudp host:%x\n ",udp->host);
    	if(udp->host) return 0;
    	else return -1;
    }
    else if (NULL != ip && 0 != port)
    {
    	int ret;
    	
    	udp->host = enet_host_create(NULL, sockfd, 1, 0,0,0);/*init client*/
    
    	ENetAddress svraddr;
    	memset(&svraddr, 0, sizeof(ENetAddress));
    
    	if (0 != enet_address_set_host(&svraddr,ip))
    	{
    		ret = -1;
    		goto final;
    		//return -1;
    	}
    	svraddr.port = port;
    

    again: udp->peer = enet_host_connect(udp->host, &svraddr, 2,0); if (NULL == udp->peer) { ret = -1; goto final; //return -1; } if (enet_host_service (udp->host, &event, 1000) > 0 && event.type == ENET_EVENT_TYPE_CONNECT) { fprintf(stdout,"#### connect host success ....\n");

    		ret = 0;
    		goto final;
    		//return 0;
    	}
    	else
    	{
    		enet_peer_reset (udp->peer);
    		if(retry < 3){
    			retry ++ ;
    			fprintf(stderr," ### connect host again ....\n");
    			goto again;
    		}
    		else{
    			ret = -1;
    			goto final;
    			//return -1;
    		}
    	}
    

    final: return ret; } }

    send function:

    int asd_reliable_udp_send(ASD_RELIABLE_UDP *udp, const void *data, size_t len) { ENetEvent event; if (NULL == udp->host || NULL == udp->peer || NULL == data || len <= 0) { fprintf(stderr,"param is error,host:%x,event.peer:%x,data:%x,len:%d\n",udp->host,udp->peer,len); return -1; }

    ENetPacket *packet = enet_packet_create(data,len,ENET_PACKET_FLAG_RELIABLE);
    if (NULL == packet)
    {
    	fprintf(stderr,"enet_packet_create failed\n");
    	return -1;
    }
    
    if (0 != enet_peer_send(udp->peer,1,packet))
    {
    	fprintf(stderr,"enet_peer_send failed,errno:%d\n",errno);
    	enet_packet_destroy(packet);
    	return -1;
    }
    
    {
    	enet_host_flush (udp->host);
    }
    return len;
    

    }

    int asd_reliable_udp_recv(ASD_RELIABLE_UDP *udp, void *data, size_t len,size_t timeout) { int datalen = 0; ENetEvent event; if (NULL == udp || NULL == udp->host || NULL == data || len <= 0) { return -1; } int err = enet_host_service(udp->host, &event, timeout); if(err >= 0) { if (event.type == ENET_EVENT_TYPE_NONE) { //fprintf(stderr,"ENET_EVNET_TYPE_NONE ..:%d\n",errno); goto fin; } else if (event.type == ENET_EVENT_TYPE_CONNECT) { goto fin; } else if(event.type == ENET_EVENT_TYPE_RECEIVE) { //fprintf(stderr,"Request len:%d,dataLeng:%d\n",len,event.packet->dataLength); memcpy(data, event.packet->data, event.packet->dataLength); datalen = event.packet->dataLength; enet_packet_destroy(event.packet); goto fin; } else if (event.type == ENET_EVENT_TYPE_DISCONNECT) { //fprintf(stderr,"event disconnect ****\n"); return -ENET_EVENT_TYPE_DISCONNECT; } } fin: return datalen; }

    opened by zhengchengbin610 10
  • Enet File sync simulation: The performance (file transfer speed) is far worse than 'scp'

    Enet File sync simulation: The performance (file transfer speed) is far worse than 'scp'

    I wanna use ENet to speed the file transfer between two hosts which have worse network connection (packet loss ratio over 5%).

    I am disappointed by the performance, it is only 110KB/S, however 'scp' can be over 1024KB/S.

    I do not think ENet fails to do such task, It must be my fault.

    The following code is very simple:

    I use 3 channels to finish the task:

    In server side:

    1)Ignite file sync by channel 0 (CONNECT event) 2) Send packet by channel 2 (Would send max 4 packets to speed the transfer and take into account of RECEIVE event delay issue) 3) Send finished message by channel 1

    In client side:

    1) Ignite file sync by channel 0 ( RECEIVE event) 2) Receive packet by channel 2 and send the received packet count by channel 0 , Server will consume the packet and reply file packet with channel 2. 3) Close file by channel 1 (RECEIVE event)

    I found some RECEIVE interval of server could be very huge( over 10s). Why? because such huge delay could degrade the file transfer speed.

    The following is my example code:

    Server.c

    `#include <stdio.h>

    include <errno.h>

    include <string.h>

    include <stdlib.h>

    include <assert.h>

    include <enet/enet.h>

    include "config.h"

    define FILENAME "/relay/100MB-tokyo.bin"

    static char file_buffer[256*1024];

    int main (int argc, char *argv[]) { ENetAddress address; ENetHost *server; ENetPacket *packet; ENetEvent event; char host_ip[32] = {0}; char peer_info[32] = {0}; char msg_notify[64] = {0}; int lastEvent = -1; int enableDebug = 0;

    FILE *fp = fopen(FILENAME, "rb");
    if (!fp) {
        fprintf(stderr, "Fail to open file.\n");
        exit(0);
    }
    
    /* Initialize the ENet */
    if (enet_initialize() != 0) {
        fprintf(stderr, "An error (%s) occured while initializing ENet.\n", strerror(errno));
        return EXIT_FAILURE;
    }
    atexit(enet_deinitialize);
    
    /* Create the server */
    address.host = ENET_HOST_ANY;
    address.port = SHUTTLE_SERVER_PORT;
    server = enet_host_create(&address, 64, 6, 0, 0);
    if (server == NULL) {
        fprintf(stderr, "An error (%s) occured while trying to create ENet server host.\n", strerror(errno));
        exit(EXIT_FAILURE);
    }
    
    enet_uint32 time0 = 0, time1 = 0, time2 = 0;
    uint64_t packet_size = 0;
    uint64_t packet_count = 0;
    int connected = 0;
    int finished = 0;
    
    printf("(Slice) Server is running.\n");
    while (1) {
        /* Event dispatcher: MUST not be hanged up. */
        int eventStatus = enet_host_service(server, &event, 2);
        if (eventStatus >= 0) {
            switch (event.type) {
            case ENET_EVENT_TYPE_NONE:
                /* Silence huge repeated NONE events. */
                if (lastEvent != ENET_EVENT_TYPE_NONE) {
                    if (enableDebug)
                        printf("(Slice) No event.\n");
                }
                break;
            case ENET_EVENT_TYPE_CONNECT:
                /* Store any relevant server information here. */
                enet_address_get_host_ip(&event.peer->address, host_ip, sizeof(host_ip) - 1);
                snprintf(peer_info, sizeof(peer_info), "[%s:%d]", host_ip, event.peer->address.port);
                if (event.peer->data)
                    free(event.peer->data);
                event.peer->data = malloc(strlen(peer_info) + 1);
                if (event.peer->data)
                    strcpy(event.peer->data, peer_info);
                snprintf(msg_notify, sizeof(msg_notify), "%s has connected to server", peer_info);
                connected = 1;
                finished = 0;
                time0 = enet_time_get();
                /* Ignite packet sync */
                packet = enet_packet_create(msg_notify, strlen(msg_notify) + 1, ENET_PACKET_FLAG_RELIABLE);
                enet_peer_send(event.peer, 0, packet);
                enet_host_flush(server);
                printf("(Slice) Got a connection from peer: %s:%d.\n", host_ip, event.peer->address.port);
                break;
            case ENET_EVENT_TYPE_RECEIVE:
                time1 = enet_time_get() - time0;
                printf("(Slice) Time: %d, Channel: %d.\n", time1 - time2, event.channelID);
                time2 = time1;
                if (connected) {
                    int64_t received_count = atoi((char*)event.packet->data);
                    while (!finished && received_count + 4 > packet_count) {
                        int ret = fread(file_buffer, 1, sizeof(file_buffer), fp);
                        if (!ret) {
                            printf("(Slice) File sync has finished.\n");
                            if (received_count == packet_count) {
                                finished = 1;
                                snprintf(file_buffer, sizeof(file_buffer), "%d", 1);
                                packet = enet_packet_create(file_buffer, strlen(file_buffer) + 1, ENET_PACKET_FLAG_RELIABLE);
                                enet_peer_send(event.peer, 1, packet);
                                enet_host_flush(server);
                            }
                            break;
                        }
                        packet_size += ret;
                        packet = enet_packet_create(file_buffer, ret, ENET_PACKET_FLAG_RELIABLE);
                        packet_count++;
                        enet_peer_send(event.peer, 2, packet);
                        enet_host_flush(server);
                    }
                    printf("(Slice) packet: received:%d, send: %d, speed: %dKB/S.\n",
                           (int)received_count, (int)packet_count, (int)(packet_size*1000/(time1 * 1024)));
                }
                /* Clean up the packet now that we're done using it. */
                enet_packet_destroy(event.packet);
                break;
            case ENET_EVENT_TYPE_DISCONNECT:
                /* A connected peer has either explicitly disconnected or timed out. */
                if (event.peer->data) {
                    printf("(Slice) %s is disconnected.\n", (char*)event.peer->data);
                    free(event.peer->data);
                } else {
                    enet_address_get_host_ip(&event.peer->address, host_ip, sizeof(host_ip) - 1);
                    snprintf(peer_info, sizeof(peer_info), "[%s:%d]", host_ip, event.peer->address.port);
                    printf("(Slice) Unknown (%s) connection is disconnected.\n", peer_info);
                }
                /* Reset the peer's information. */
                event.peer->data = NULL;
                enet_peer_reset(event.peer);
                lastEvent = -1;
                break;
            default:
                assert(0);
                break;
            }
    
            lastEvent = event.type;
        } else {
            fprintf(stderr, "(Slice) Something went wrong: %d.\n", eventStatus);
            lastEvent = -1;
        }
    }
    
    enet_host_flush(server);
    fclose(fp);
    
    enet_host_destroy(server);
    printf("Server is terminated.\n");
    
    return 0;
    

    } `

    Clinet.c

    `#include <stdio.h>

    include <errno.h>

    include <string.h>

    include <stdlib.h>

    include <assert.h>

    include <pthread.h>

    include <enet/enet.h>

    include "config.h"

    typedef struct ChatContext { ENetHost *client; ENetPeer *peer; volatile int connected; volatile int terminated; } ChatContext;

    int main (int argc, char *argv[]) { ENetAddress address; ENetEvent event; ChatContext cc, *pcc = &cc; char host_ip[32] = {0}; char peer_info[32] = {0}; int lastEvent = -1; int enableDebug = 0; int trycount = 0; int ret;

    memset(pcc, 0, sizeof(*pcc));
    
    /* Initialize the ENet */
    if (enet_initialize() != 0) {
        fprintf(stderr, "An error (%s) occured while initializing ENet.\n", strerror(errno));
        return EXIT_FAILURE;
    }
    atexit(enet_deinitialize);
    
    /* Create the client host */
    pcc->client = enet_host_create(NULL, 64, 6, 0, 0);
    if (pcc->client == NULL) {
        fprintf(stderr, "An error (%s) occured while trying to create an ENet client host.\n", strerror(errno));
        exit(EXIT_FAILURE);
    }
    
    /* Connect to the server */
    enet_address_set_host(&address, SHUTTLE_SERVER_HOST);
    address.port = SHUTTLE_SERVER_PORT;
    pcc->peer = enet_host_connect(pcc->client, &address, 6, 0);
    if (pcc->peer == NULL) {
        fprintf(stderr, "No available peers for initializing an ENet connection.\n");
        exit(EXIT_FAILURE);
    }
    
    do {
        trycount++;
        printf("(Peer) Try to connect to server: the %dth tryouts.\n", trycount);
        if (enet_host_service(pcc->client, &event, 1000) > 0 && event.type == ENET_EVENT_TYPE_CONNECT) {
            /* We can send packet to server only after we have received ENET_EVENT_TYPE_CONNECT */
            pcc->connected = 1;
            enet_address_get_host_ip(&event.peer->address, host_ip, sizeof(host_ip) - 1);
            snprintf(peer_info, sizeof(peer_info), "[%s:%d]", host_ip, event.peer->address.port);
            if (event.peer->data)
                free(event.peer->data);
            event.peer->data = malloc(strlen(peer_info) + 1);
            if (event.peer->data)
                strcpy(event.peer->data, peer_info);
            printf("(Peer) Connected to server (%s:%d).\n", host_ip, event.peer->address.port);
        }
    } while (trycount < 4 && !pcc->connected);
    
    if (!pcc->connected) {
        fprintf(stderr, "Fail to connect to server.\n");
        enet_peer_reset(pcc->peer);
        enet_host_destroy(pcc->client);
        exit(EXIT_FAILURE);
    }
    
    FILE *fp = fopen("/mnt/sdc/tmp/file_sync.bin", "wb");
    if (!fp) {
        fprintf(stderr, "Fail to write file.\n");
        exit(0);
    }
    
    enet_uint32 time0 = 0, time1 = 0, time2 = 0;
    int64_t packet_size = 0;
    int64_t packet_count = 0;
    char packet_info[32] = {0};
    
    while (1) {
        /* Event dispatcher: MUST not be hanged up */
        int eventStatus = enet_host_service(pcc->client, &event, 2);
        if (eventStatus >= 0) {
            switch (event.type) {
            case ENET_EVENT_TYPE_NONE:
                /* Silence huge repeated NONE events */
                if (lastEvent != ENET_EVENT_TYPE_NONE) {
                    if (enableDebug)
                        printf("(Peer) No event.\n");
                }
                break;
            case ENET_EVENT_TYPE_CONNECT:
                /* Store any relevant client information here. */
                pcc->connected = 1;
                enet_address_get_host_ip(&event.peer->address, host_ip, sizeof(host_ip) - 1);
                snprintf(peer_info, sizeof(peer_info), "[%s:%d]", host_ip, event.peer->address.port);
                if (event.peer->data)
                    free(event.peer->data);
                event.peer->data = malloc(strlen(peer_info));
                if (event.peer->data)
                    strcpy(event.peer->data, peer_info);
                printf("(Peer) Connected to server (%s:%d).\n", host_ip, event.peer->address.port);
                break;
            case ENET_EVENT_TYPE_RECEIVE:
                if (time0 != 0) {
                    time1 = enet_time_get() - time0;
                    printf("(Peer) Time: %d, Channel: %d.\n", time1 - time2, event.channelID);
                    time2 = time1;
                }
                if (event.channelID == 0) {
                    /* Ignite packet sync */
                    packet_count = 0;
                    snprintf(packet_info, sizeof(packet_info), "%d", (int)packet_count);
                    ENetPacket *packet = enet_packet_create(packet_info, strlen(packet_info) + 1, ENET_PACKET_FLAG_RELIABLE);
                    enet_peer_send(event.peer, 0, packet);
                    enet_host_flush(pcc->client);
                    time0 = enet_time_get();
                }
                else if (event.channelID == 2) {
                    packet_count++;
                    time1 = enet_time_get() - time0;
                    packet_size += event.packet->dataLength;
                    if (fp) {
                        printf("(Peer) channelID:%d, len:%ld.\n", event.channelID, event.packet->dataLength);
                        fwrite(event.packet->data, 1, event.packet->dataLength, fp);
                    }
                    printf("(Peer) Receive speed: %d KB/S.\n", (int)(packet_size*1000/(time1*1024)));
                    snprintf(packet_info, sizeof(packet_info), "%d", (int)packet_count);
                    ENetPacket *packet = enet_packet_create(packet_info, strlen(packet_info) + 1, ENET_PACKET_FLAG_RELIABLE);
                    enet_peer_send(event.peer, 0, packet);
                    enet_host_flush(pcc->client);
                } else if (event.channelID == 1) {
                    if (fp) {
                        fclose(fp);
                        fp = 0;
                    }
                }
                else 
                    printf("(Peer) Got a chat message: %s.\n", (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:
                /* A connected peer has either explicitly disconnected or timed out. */
                printf("(Peer) Connection status: %d.\n", pcc->connected);
                if (event.peer->data) {
                    printf("(Peer) %s is disconnected.\n", (char*)event.peer->data);
                    free(event.peer->data);
                } else {
                    /* We fail to receive CONNECT event becasue the server is down. */
                    enet_address_get_host_ip(&event.peer->address, host_ip, sizeof(host_ip) - 1);
                    snprintf(peer_info, sizeof(peer_info), "[%s:%d]", host_ip, event.peer->address.port);
                    printf("(Peer) Unknown (%s) connection is disconnected.\n", peer_info);
                }
                /* Reset the peer's information. */
                event.peer->data = NULL;
                pcc->connected = 0;
                lastEvent = -1;
                enet_peer_reset(event.peer);
                /* Reconnect the server */
                pcc->peer = enet_host_connect(pcc->client, &address, 6, 0);
                if (pcc->peer == NULL) {
                    fprintf(stderr, "No available peers for initializing an ENet connection.\n");
                    enet_host_destroy(pcc->client);
                    ret = EXIT_FAILURE;
                    goto cleanup_pos;
                }
                break;
            default:
                assert(0);
                break;
            }
    
            lastEvent = event.type;
        } else {
            fprintf(stderr, "(Peer) Something went wrong: %d.\n", eventStatus);
            lastEvent = -1;
            pcc->connected = 0;
            enet_peer_reset(pcc->peer);
            ret = eventStatus;
            goto cleanup_pos;
        }
    }
    
    ret = 0;
    

    cleanup_pos: if (fp) fclose(fp); pcc->terminated = 1; enet_host_destroy(pcc->client); printf("Client is terminated.\n");

    return ret;
    

    } `

    opened by nxtreaming 10
  • [FIX] CRC32 data race when using multiple ENetHost's from distinct threads

    [FIX] CRC32 data race when using multiple ENetHost's from distinct threads

    Hello!

    I have noticed that when using ENet from multiple threads, the CRC32 checksum sometimes seems to have miscalculations, resulting in unwanted retransmissions within ENet itself when a packet was sent with ENET_PACKET_FLAG_RELIABLE, even worse is that such packets would've been discarded completely if the reliability flag wasn't set, as the checksum wouldn't match...

    As many codebases make use of multithreading (since it is favorable to utilize the CPU to its full extent), the only viable way is to either supply multiple ENetHost's (e.g when wanting to deploy multiple servers for a service), or when wanting to have multiple clients separately with the full performance of all CPU cores.

    image ENet (according to the image), promises to work fine in a multithreaded environment, however I believe this may not apply to the checksum calculation, as that seems to require static global variables such as "crcTable" and "initializedCRC32". This could break the promise of full thread-safety even when the end-user makes sure that the ENetHosts operate distinct and separately.

    As a result, a modification (in my opinion an improvement) had to be done to the design of ENet: enet_uint32 crcTable[256] and int initializedCRC32 are now members of the ENetHost structure. For authenticity, enet_crc32 and the ENetChecksumCallback now have to be called with an ENetHost pointer and enet_crc32 is now called enet_host_crc32. For the internal initialization, enet_host_initialize_crc32 is now being used to initialize ENet's implementation of the CRC32 checksum.

    The reason I believe this is also more authentic, is because the ENetInterceptCallback also requires an ENetHost * - already. Now by making crcTable and initializedCRC32 members of ENetHost, it has also been made necessary to pass an ENetHost * to the checksum callback - in order to fix the data race / minuscule multithreading issue as mentioned above.

    opened by playingoDEERUX 9
  • Add the depencies to readme.md

    Add the depencies to readme.md

    Please add the toolchain requirements to the projects readme.md, otherwise it might be difficult to detect compilation errors (m4 is a bit cryptic on that). The depencies on Ubuntu 14.04 are:

    opened by Fohlen 9
  • Lag over time?

    Lag over time?

    I'm having a strange issue with ENet which I can't narrow down. I'm sending packets between two peers every frame, initially the packets arrive on time within 1 frame of each-other since both clients are running on the same machine for testing. But after about a minute passes, the packets start becoming more and more delayed. To where packets arrive 30 frames late. I'm not doing anything in my game loop which would cause delay in sending or receiving the packets since both clients are running consistent 70 fps. Is this a known issue with ENet? Has anyone else experienced it? To give a small demonstration of what's happening, here's two rectangles moving around. The one on the left is being controlled while the one on the right is seeing the result across the network. The one on the right is receiving the packets much later than when they were actually sent.. Even though they're both running on the same machine. The packets I am sending (PacketTransmission) is only 16 bytes.

    https://imgur.com/bumbAvg https://i.imgur.com/bumbAvg.mp4

    This is how I'm sending the packets.

        ENetPacket *packet = enet_packet_create((uint8_t*)pt,
                                                sizeof(PacketTransmission),
                                                ENET_PACKET_FLAG_RELIABLE);
    
        enet_peer_send(c->natpeer, 0, packet);
    
    opened by JadeVand 8
  • Connection timeout when 2 enet host in same process

    Connection timeout when 2 enet host in same process

    In the mar 4 commit seems that the connected peer disconnected after ~1 second. This happen when you create 2 enet hosts in same process and connect to one another.

    opened by Benau 7
  • Round trip time varies with update rate

    Round trip time varies with update rate

    Consider the following: if enet_host_service is called once every second (in a while loop, as usual) in one end while the other end is producing packets every 100ms, with no network jitter, the enet_host_service loop should run 10 times thus consuming 10 packets. In the receiving end, it looks as if all packets had arrived at the same time, but on a system level, they have all arrived within 100ms of one another. Do the system calls and structures provide any information about the time a packet arrived? This information is important when measuring relative time quantities such as RTT and synchronizing clocks. Is the only solution to call enet_host_service at a higher rate or even have a dedicated networking thread which calls enet_host_service with no timeout, thus processing incoming packets as quickly as possible?

    The issue described above seems to be the reason why ENetPeer::roundTripTime decreases as the client and server update rates go up (e.g. disabling vsync on the client). If a ping packet arrives right after the enet_host_service loop is done, it will only be processed in the next update (e.g. 16ms later) and the pong will be sent back with a significant delay, thus causing the RTT calculations to be imprecise. At the same time, if the ping packet arrives when enet_host_service is called, the pong with be sent immediately. If the client and server are running on the same machine, it looks like you'd have ping-pong sequences that take 16ms while the next one takes near 0ms, thus resulting in large variance.

    opened by xissburg 6
  • How many consecutive connections can enet handle?

    How many consecutive connections can enet handle?

    I'm using Godot game engine to create a multiplayer game, it supports UDP, TCP and websockets. According to my research UDP is the only one reliable, they use Enet.

    I didn't get a decisive answer from godot community on how many consecutive connections Enet can handle, many create a new server instance using docker per room, I don't like that

    I want to have 8 players per room, how many consecutive connections can Enet handle before that I have to create a new docker instance? If there's no good answer, I'd like to know the safest bet before creating an instance.

    opened by elieobeid7 6
  • Does ENet application compatible with another application written by original UDP?

    Does ENet application compatible with another application written by original UDP?

    I have been read some docs about ENet, ENet don't integrate TCP and UDP, It uniform protocol layered over UDP to the developer with the best features of UDP and TCP as well as some useful features neither provide. I have little confused:

    Does Enet have special self-custom data struct in application layer protocal, or does it do these under application layer, so user will be used in transparent mode?

    Two application written by ENet using reliable udp (server,client) should be work fine, but is it fine as change one to original UDP?

    I just need a usable reliable UDP library can working with another UDP server or client, may be they have reliable or none reliable(original UDP), ENet suitable?

    opened by xpbigapple02 0
  • Can enet support epoll()

    Can enet support epoll()

    ^^ Question in title, I believe epoll has some great performance/scalability advantages that I would like to see in ENet! Any way that's going to be added in the future?

    opened by playingoDEERUX 0
  • data (4th) argument of enet_host_connect() is not set in the CONNECT event received on the CLIENT side.

    data (4th) argument of enet_host_connect() is not set in the CONNECT event received on the CLIENT side.

    (Updated after stand-alone repro showed the the SERVER side sees the value, but the CLIENT side does not.)

    The docs for enet_host_connect() state that the final argument, enet_uint32 data is "user data supplied to the receiving host". Sadly when the sending (client) host receives the ENET_EVENT_TYPE_CONNECT event, that data value is NOT set in the ENetEvent->data member; the value is always zero. In fact, none of the data members reachable from the event (such as event->peer->data or event->peer->eventData) have the magic 32-bit value that I specified in my call to enet_host_connect().

    My intent was to use this value on the server side to allow the server to reject a client that did not specify the expected 32-bit value. However, my own project uses common code (both the client and server end) to run the ENet "while / switch" event pump.

    Confirmed w/ GDB:

    // 32-bit value sent from client to server when connecting.
    // The server end will reject any client that fails to provide this value.
    // This is to reduce errant connection attempts from other ENet clients.
    constexpr uint32_t kConnectionSentinal = 0x50564500; // "PVE\000"
    ...
      std::unique_lock<std::mutex> enet_lock(enet_mutex_);
      enet_host_connect(enet_host_.get(), &address, kMaxChannels, kConnectionSentinal);
    ...
    
    Thread 3 "unit_tests" hit Breakpoint 1, pve::NetworkDriver::HandleConnect (this=0x7fffffffd5f0, event=0x7ffff6f2bc20) at ../src/lib/common/net_driver.cc:336
    336     void NetworkDriver::HandleConnect(ENetEvent *event) {
    (gdb) p event
    $1 = (ENetEvent *) 0x7ffff6f2bc20
    (gdb) p *event
    $2 = {type = ENET_EVENT_TYPE_CONNECT, peer = 0x5555558e94f0, channelID = 0 '\000', data = 0, packet = 0x0}
    

    Application logs:

    [2022-03-29 21:38:35.262] [warning] NetworkDriver::HandleConnect 127.0.0.1:58676 Client provided invalid sentinal value of 0, expecting 1347831040
    <onehittoaster> ../src/lib/common/net_driver_test.cc:90: Failure
    

    I can confirm w/ wireshark that my uint32 is present in the UDP packet going from the client to the server. The last 4 bytes of the outbound packet (wireshark capture is from a different run of the same test, so the UDP port numbers are different, as is the connectionID; but its all the same code):

    00000000  8f ff b0 0c 82 ff 00 01  00 00 ff ff 00 00 05 78   ........ .......x
    00000010  00 01 00 00 00 00 00 02  00 00 00 00 00 00 00 00   ........ ........
    00000020  00 00 13 88 00 00 00 02  00 00 00 02 25 a4 f6 38   ........ ....%..8
    00000030  50 56 45 00                                        PVE.
        00000000  80 00 b0 0c 83 ff 00 01  00 00 00 00 00 00 05 78   ........ .......x
        00000010  00 01 00 00 00 00 00 02  00 00 00 00 00 00 00 00   ........ ........
        00000020  00 00 13 88 00 00 00 02  00 00 00 02 25 a4 f6 38   ........ ....%..8
    00000034  80 00 b0 0c 01 ff 00 01  00 01 b0 0c 85 ff 00 02   ........ ........
        00000030  00 00 01 ff 00 02 00 02  b0 0c                     ........ ..
    
    opened by dennisjenkins75 8
  • Add GitHub Actions CI

    Add GitHub Actions CI

    This adds some basic CI builds via GitHub Actions.

    This produces a build matrix [Linux, Windows, MacOS] x [Debug, Release] and builds ENet with CMake with the default detected compiler in the respective GitHub Actions environment (currently: GCC 9, Visual Studio 2019 and Apple Clang 13).

    Later on, this could be extended to cover more compilers, compiler versions and build systems (Makefile, Premake), but it is a start to get some CI going for ENet.

    An exemplary run can be seen here: https://github.com/Croydon/enet/actions/runs/1723356026

    If this is merged, GitHub will run this CI for every future push and pull request, no further configuration is required whatsoever.

    opened by Croydon 0
  • Add install to CMakeLists.txt

    Add install to CMakeLists.txt

    Currently CMakeLists.txt lacks any installation instruction, which is a bit annoying when you wish to install it in system folders (using make install), this PR fixes that.

    opened by SirLynix 1
Owner
Lee Salzman
Lee Salzman
Reliable & unreliable messages over UDP. Robust message fragmentation & reassembly. P2P networking / NAT traversal. Encryption.

GameNetworkingSockets GameNetworkingSockets is a basic transport layer for games. The features are: Connection-oriented API (like TCP) ... but message

Valve Software 6.2k Sep 17, 2022
Data-oriented networking playground for the reliable UDP transports

NetDynamics is a data-oriented networking playground for the reliable UDP transports. The application was created for stress testing and debugging a p

Stanislav Denisov 91 Aug 28, 2022
First Growtopia Private Server made with ENet

GrowtopiaServer First Growtopia Private Server made with ENet. This project has been compiled with Visual Studio 2015 (Visual Studio 2013 or older won

Lyte 10 Oct 21, 2021
Mongoose Embedded Web Server Library - a multi-protocol embedded networking library with TCP/UDP, HTTP, WebSocket, MQTT built-in protocols, async DNS resolver, and non-blocking API.

Mongoose - Embedded Web Server / Embedded Networking Library Mongoose is a networking library for C/C++. It implements event-driven non-blocking APIs

Cesanta Software 8.7k Sep 18, 2022
Portable, single-file, protocol-agnostic TCP and UDP socket wrapper, primarily for game networking

Documentation This is a header-only library, as such most of its functional documentation is contained within the "header section" of the source code

null 65 Aug 29, 2022
:zap: KCP - A Fast and Reliable ARQ Protocol

KCP - A Fast and Reliable ARQ Protocol README in English 简介 KCP是一个快速可靠协议,能以比 TCP 浪费 10%-20% 的带宽的代价,换取平均延迟降低 30%-40%,且最大延迟降低三倍的传输效果。纯算法实现,并不负责底层协议(如UDP

Linwei 11.7k Sep 17, 2022
Lightway Core is a modern VPN protocol by ExpressVPN, to deliver a VPN experience that’s faster, more secure, and more reliable.

Lightway Core NOTE: This is a preview snapshot of the Lightway repository used for both our client and server. We will be publishing a live, actively

ExpressVPN 22 Feb 17, 2022
Lightway Core is a modern VPN protocol by ExpressVPN, to deliver a VPN experience that’s faster, more secure, and more reliable.

Lightway Core is a modern VPN protocol by ExpressVPN, to deliver a VPN experience that’s faster, more secure, and more reliable.

ExpressVPN 331 Sep 9, 2022
The C++ Network Library Project -- cross-platform, standards compliant networking library.

C++ Network Library Modern C++ network programming libraries. Join us on Slack: http://slack.cpp-netlib.org/ Subscribe to the mailing list: https://gr

C++ Network Library 1.9k Sep 22, 2022
Ultra fast and low latency asynchronous socket server & client C++ library with support TCP, SSL, UDP, HTTP, HTTPS, WebSocket protocols and 10K connections problem solution

CppServer Ultra fast and low latency asynchronous socket server & client C++ library with support TCP, SSL, UDP, HTTP, HTTPS, WebSocket protocols and

Ivan Shynkarenka 885 Sep 17, 2022
A modern C++ network library for developing high performance network services in TCP/UDP/HTTP protocols.

evpp Introduction 中文说明 evpp is a modern C++ network library for developing high performance network services using TCP/UDP/HTTP protocols. evpp provid

Qihoo 360 3.1k Sep 22, 2022
canonical libwebsockets.org networking library

Libwebsockets Libwebsockets is a simple-to-use, MIT-license, pure C library providing client and server for http/1, http/2, websockets, MQTT and other

lws-team 3.6k Sep 17, 2022
Backroll is a pure Rust implementation of GGPO rollback networking library.

backroll-rs Backroll is a pure Rust implementation of GGPO rollback networking library. Development Status This is still in an early beta stage. At ti

Hourai Teahouse 244 Sep 15, 2022
requests-like networking library using boost for C++

cq == C++ Requests cq == C++ Requests is a "Python Requests"-like C++ header-only library for sending HTTP requests. The library is inspired a lot by

null 11 Dec 15, 2021
C++ networking library including UniConf and a convenient D-Bus API

This is wvstreams, a nominally platform-independent networking and utilities library for C++. Some documentation is in the Docs/ directory. If that

null 27 Dec 29, 2021
Socket and Networking Library using msgpack.org[C++11]

netLink C++ 11 KISS principle networking library. Features: C++ 11 IPv4, IPv6 Protocols: TCP, UDP Enable/Disable blocking mode Join/Leave UDP-Multicas

Alexander Meißner 208 Sep 9, 2022
Small and fast cross-platform networking library, with support for messaging, IPv6, HTTP, SSL and WebSocket.

frnetlib Frnetlib, is a cross-platform, small and fast networking library written in C++. There are no library dependencies (unless you want to use SS

Fred Nicolson 22 May 16, 2022
A simple networking library for C++. Designed with games in mind, but can be used for other things

A simple networking library for C++. Designed with games in mind, but can be used for other things. Tested to work on Android and Windows.

Matthew 5 Nov 14, 2019
Single file public domain networking library

zed_net zed_net is a single file, public domain library that provides a simple wrapper around BSD sockets (Winsock 2.2 on Windows), intended primary f

Ian T. Jacobsen 50 Jul 18, 2022