Trouble understanding Enet tutorial

Started by
16 comments, last by hplus0603 10 years, 6 months ago

Apparently people report that they are not accurate.

Advertisement

Ok, I need some help. On the server side, the event->peer->data member gets overwritten such that all packets looks like they come from the same source. If I connect 3 clients to the server, all packets seems to come from the last ip:port connected!? I thought that Enet filled all event->peer fields during enet_host_service (server, &event, 1000)?


	//Main Loop
	bool loop = true;
	while(loop){
		ENetEvent event;
		/* Wait up to 1000 milliseconds for an event. */
		while (enet_host_service (server, &event, 1000) > 0){
			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. */
				long long ipandport;
				char buffer[64];
				in_addr addr;
				addr.S_un.S_addr = event.peer->address.host;
				sprintf_s(buffer, "%s:%d", inet_ntoa(addr), event.peer->address.port);
				event.peer->data = buffer;	//Overwritten for all peers????

				ipandport = *((long long*) (&event.peer->address));
				cout << "Registered user: " << ipandport << endl;
				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,	//All packets are from same IP:Port???
					event.channelID);        
				/* Clean up the packet now that we're done using it. */
				if(event.packet != NULL){
					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;    
			}
		}
	}

Your problem is that you are assigning the "data" member a value that is a pointer to a buffer on the stack.

enum Bool { True, False, FileNotFound };

Right. The tutorial is very misleading here. It sets event.peer->data = "Client information";. Where this string is constant inside the binary...

I am trying to use a std::shared_ptr and attach it to event.peer->data but I have some difficulties. Mainly casting between void* and

std::shared_pr<mystruct>. Got any input?

I want to stay away from raw pointers, don't want to risk leaks if a disconnect does not get recieved such that the delete operator does not get called or something buggy like that.


case ENET_EVENT_TYPE_CONNECT:
	{
		char buffer[64];
		in_addr addr;
		long long ipandport = (netevent.peer->address.host << 16) | netevent.peer->address.port;		//Unique ID
		std::shared_ptr<PeerData> spNewPeer(new PeerData);
		spNewPeer->ipandport = ipandport;
		spNewPeer->peer = netevent.peer;
		addr.S_un.S_addr = netevent.peer->address.host;
		sprintf_s(buffer, "%s:%d", inet_ntoa(addr), netevent.peer->address.port);
		printf("A new client connected from %s.\n", buffer);
		spNewPeer->sipandport = string(buffer);
		netevent.peer->data = &(*spNewPeer);						//assigning, might be bad....
		cout << "Registered user: " << ipandport << endl;
		break;
	}
case ENET_EVENT_TYPE_RECEIVE:
	{
		std::shared_ptr<PeerData> spPeer(netevent.peer->data);
		cout << "A packet of length " << netevent.packet->dataLength 
			<< " containing " << netevent.packet->data 
			<< " was received from " << spPeer->sipandport			//causes compile errors, cannot convert parameter 1 from 'void *' to 'PeerData *'
			<< " on channel" << netevent.channelID << "." << endl;

		if(netevent.packet != NULL){
			enet_packet_destroy (netevent.packet);
		}
		break;
	}

In the end, you will probably want to have the network code completely independent of the game code - logically (game code) and technically (update rate ie.). I'd just take the data pointer from packet, copy the data into your structure and release the event. Then pass your structure into "higher levels" (session, game).

The tutorial is very misleading here. It sets event.peer->data = "Client information";. Where this string is constant inside the binary...
I am trying to use a std::shared_ptr and attach it to event.peer->data but I have some difficulties. Mainly casting between void* and
std::shared_pr<mystruct>. Got any input?


I don't think the tutorial is misleading at all. The semantics of pointsrs and the lifetime of the data they point to is very well known to C and C++ programmers and a fundamental concept of the language.

A void* is not a shared pointer, and cannot be a shared pointer. Sizeof(shared_ptr) is larger than sizeof(void*).

I suggest you make the "data" point to some object you allocate yourself, and when you are notified about the peer object going away, properly delete that object.
enum Bool { True, False, FileNotFound };

Thanks all for the input. I have encapsulated Enet in my own working class with this interface.


	bool Connect(char* Name, char* HostName, unsigned short port);
	void Disconnect();
	DWORD GetStatus();
	bool Tick(ENetEvent* RecvPacket);
	void Send(EnetBaseMessage *message);
	void FlushPackets();
	const char* GetUserName();
	ENetPeer* GetPeer();

Tick() returns true if there is a packet, this is how I "while(tick(&packet))" the incoming packets from. I can also inject to the packet information such as "disconnected".

The ping info inside the peer is 15ms higher then I get from normal pinging the server. The incomingDataTotal and outgoingDataTotal makes no sense.

The ping info inside the peer is 15ms higher then I get from normal pinging the server


That probably reflects the difference between just sending ICMP packets that are returned by the kernel, and measuring actual application messaging latency that involves the entire messaging stack.
enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement