Results 1 to 3 of 3

Thread: So I created an ENet component for potential multiplayer functionality (now what?)

  1. #1
    Lesser Wizard
    Join Date
    Nov 2010
    Location
    Los Angeles, California, United States, United States
    Posts
    126

    Default So I created an ENet component for potential multiplayer functionality (now what?)

    Seth I got ENet up and running with few issues. I mainly ran into linker issues between winsock.h and winsock2.h (latter of which is required for enet).

    Below are examples and the (albeit not that functional and poorly named) component.

    Question before you move on:
    There's likely a better way of doing this (i.e. using another thread, not using components, binding to a different function). What do you recommend?

    For a server:
    Code:
    	NetServerComponent* pComp = new NetServerComponent();
    	pBG->AddComponent(pComp);
    	pComp->InitServer(1234); // init server on port 1234
    For a client:
    Code:
            // adding client...
    	NetServerComponent* pComp = new NetServerComponent();
    	pBG->AddComponent(pComp);
    	pComp->InitClient();
    	pComp->ConnectToHost("192.168.1.11", 1234);
    	
    	// create our packet
    	NetPacket np;
    	strcpy(np.message, "Hello World!!!");
    	np.nFlags = 69;
    	
    	// send the message!
    	pComp->SendPacket(&np);
    Here is the component source:
    Code:
    #ifndef NetServerComponent_h__
    #define NetServerComponent_h__
    
    #include "Entity/Component.h"
    #include "enet/enet.h"
    
    typedef struct 
    {
    	char nID[32];
    	char message[40];
    	uint32 nFlags;
    } NetPacket;
    
    class NetServerComponent: public EntityComponent
    {
    public:
    	NetServerComponent();
    	virtual ~NetServerComponent();
    
    	virtual void OnAdd(Entity *pEnt);
    	virtual void OnRemove();
    
    	enum eState
    	{
    		STATE_IDLE,
    		STATE_CONNECTING,
    		STATE_CONNECTED,
    		STATE_FINISHED
    	};
    	
    	void InitServer(uint16 u16Port);
    	void InitClient();
    	void ConnectToHost(char* address, uint16 u16Port);
    	void SendPacket(NetPacket* np);
    
    private:
    
    	void OnUpdate(VariantList *pVList);
    	void OnRender(VariantList *pVList);
    	
    	void KillServer();
    	
    	void ProcessMessages();
    	
    	// enet
    	ENetHost* m_host;
    	ENetPeer* m_peer;
    };
    
    #endif // NetServerComponent_h__
    Code:
    #include "PlatformPrecomp.h"
    
    #include "NetServerComponent.h"
    
    NetServerComponent::NetServerComponent()
    {
    	SetName("NetServer");
    
    	m_host = 0;
    	m_peer = 0;
    }
    
    NetServerComponent::~NetServerComponent()
    {
    }
    
    void NetServerComponent::OnAdd(Entity *pEnt)
    {
    	EntityComponent::OnAdd(pEnt);
    
    	//register ourselves to render if the parent does
    	pEnt->GetFunction("OnRender")->sig_function.connect(1, boost::bind(&NetServerComponent::OnRender, this, _1));
    	pEnt->GetFunction("OnUpdate")->sig_function.connect(1, boost::bind(&NetServerComponent::OnUpdate, this, _1));
    }
    
    void NetServerComponent::OnRemove()
    {
    	EntityComponent::OnRemove();
    
    	// kill our server and shut down enet
    	KillServer();
    }
    
    void NetServerComponent::OnRender(VariantList *pVList)
    {
    	//OnUpdate(pVList);
    }
    
    void NetServerComponent::OnUpdate(VariantList *pVList)
    {
    	ProcessMessages();
    }
    
    void NetServerComponent::KillServer()
    {	
    	// shut down the server
    	enet_host_destroy(m_host);
    	
    	// de-init enet
    	enet_deinitialize();		
    }
    
    void NetServerComponent::InitClient()
    {
    	// init enet
    	if(enet_initialize() == 0)
        {
    		m_host = 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, //57600 / 8 /* 56K modem with 56 Kbps downstream bandwidth */,
    								 0); //14400 / 8 /* 56K modem with 14 Kbps upstream bandwidth */);
    	
    		if (!m_host)
    		{
    			LogError("An error occurred while trying to create an ENet client host.\n");
    		}
    	}
    	else 
    	{
    		LogError("An error occurred while initializing ENet.\n");
        }
    }
    
    void NetServerComponent::InitServer(uint16 u16Port)
    {
    	// init enet
    	if(enet_initialize() == 0)
        {
    		ENetAddress address;
    		
    		// Bind the server to the default localhost.
    		address.host = ENET_HOST_ANY;
    		address.port = u16Port;  
    		
    		m_host = 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 (!m_host)
    		{
    			LogError("An error occurred while trying to create an ENet server host.\n");
    		}
    	}
    	else 
    	{
    		LogError("An error occurred while initializing ENet.\n");
        }
    }
    
    void NetServerComponent::ConnectToHost(char* szAddress, uint16 u16Port)
    {
    	ENetAddress address;
        ENetEvent event;
    	
        /* Connect to 192.168.1.11:1234. */
        enet_address_set_host(&address, szAddress);
        address.port = u16Port;
    	
        /* Initiate the connection, allocating the two channels 0 and 1. */
        m_peer = enet_host_connect(m_host, &address, 2, 0);    
        
        if(!m_peer)
        {
    		LogError("No available peers for initiating an ENet connection.\n");
        }
        
    	m_peer->data = 0; // use this as mark that connection is not yet acknowledged
    
        /* Wait up to 5 seconds for the connection attempt to succeed. */
        if(enet_host_service (m_host, & event, 5000) > 0 &&
    	   event.type == ENET_EVENT_TYPE_CONNECT)
        {
            LogMsg("Connection to %s:%u succeeded.", szAddress, u16Port);
        }
        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 (m_peer);
    		
            LogMsg("Connection to %s:%u FAILED.", szAddress, u16Port);
        }
    }
    
    void NetServerComponent::SendPacket(NetPacket* np)
    {
    	//void* data;
    	//memcpy(&data, &np, sizeof(np));
        /* Create a reliable packet of size 7 containing "packet\0" */
        ENetPacket * packet = enet_packet_create(np, sizeof(NetPacket), ENET_PACKET_FLAG_RELIABLE);
        //ENetPacket * packet = enet_packet_create ("Hello World", 10 + 1, ENET_PACKET_FLAG_RELIABLE);
    
        /* Send the packet to the peer over channel id 0. */
        /* One could also broadcast the packet by         */
        /* enet_host_broadcast (host, 0, packet);         */
        if(  enet_peer_send (m_peer, 0, packet) != 0 )
    	{
    		LogMsg("Error sending packet with message: %u", packet->data);
    	}
     
    	/* One could just use enet_host_service() instead. */
        enet_host_flush (m_host);     
    }
    
    
    void NetServerComponent::ProcessMessages()
    {
    	ENetEvent event;
    	
    	if( !m_host ) 
    		return;
    
    	LogMsg("waiting for events...");
    
    	/* Wait up to 100 milliseconds for an event. */
        while (enet_host_service (m_host, &event, 100) > 0)
        {
    		LogMsg("got an event...");
    
            switch (event.type)
            {
    			case ENET_EVENT_TYPE_CONNECT:
    				LogMsg("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 = (void*)"Client information";
    				
    				break;
    				
    			case ENET_EVENT_TYPE_RECEIVE:
    				LogMsg("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);
    				
    				// convert to our packet struct
    				NetPacket np;
    				memcpy(&np, event.packet->data, sizeof(NetPacket)); 
    				LogMsg("(Server) Got Message: %s", np.message);
    
    				/* Clean up the packet now that we're done using it. */
    				enet_packet_destroy (event.packet);
    				
    				break;
    				
    			case ENET_EVENT_TYPE_DISCONNECT:
    				LogMsg("%s disconected.\n", event.peer -> data);
    				
    				/* Reset the peer's client information. */
    				event.peer -> data = NULL;
            }
        }
    }

  2. #2
    Lesser Wizard
    Join Date
    Nov 2010
    Location
    Los Angeles, California, United States, United States
    Posts
    126

    Default

    Any Chance anyone has fooled around with networking yet? Wondering if setting up another thread would be a good idea.

  3. #3
    Administrator Seth's Avatar
    Join Date
    Jul 2002
    Location
    Japan
    Posts
    5,377

    Default

    Hey BigB, thanks for sharing source. I'm using enet now too and it's working very well.

    Yeah, I had the same problem when I was using the old winsock, I make sure the examples use the newer one to possibly avoid headaches for people later.

    My setup doesn't use any extra threads (everything setup to be non-blocking), that's my preference because it makes porting across platforms easier.

    Also, one tip: if you end up needing a console based server app: Compile with the "_CONSOLE" flag (and don't include the graphical parts of the proton source) and it will work.
    Seth A. Robinson
    Robinson Technologies

Similar Threads

  1. GUI Component Constant Repaint
    By rombust in forum Official ClanLib SDK Forums
    Replies: 2
    Last Post: 10-14-2010, 07:29 AM
  2. New example in ClanLib 2.0: Custom GUI Component
    By sphair in forum Official ClanLib SDK Forums
    Replies: 4
    Last Post: 05-19-2009, 02:08 PM
  3. Potential Graphic Batcher Pitfalls (0.9)
    By rombust in forum Official ClanLib SDK Forums
    Replies: 1
    Last Post: 04-22-2009, 09:33 AM
  4. Raknet for Multiplayer
    By Amando in forum Novashell Game Creation System
    Replies: 2
    Last Post: 08-12-2008, 06:32 AM
  5. A good game with alot of potential!
    By in forum Dink Smallwood HD
    Replies: 2
    Last Post: 08-13-2004, 07:45 PM

Bookmarks

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •