And as I already explained in a different document:
int main(int argc, char** argv[]) { if (!net::init()) return 0; //todo: do something worthwhile here net::shutdown(); return 1; }
net::IPacketConnection* serverConn = net::createPacketServer(); serverConn->start(...); // do something serverConn->stop();
To receive notification of arriving packets you can supply a callback function. It will called whenever a packet is available or, if you use manual packet extraction, whenever connection's handleReceivedPackets() function is called.
Example 1 : Static function callback
using namespace net; // No namespace collisions expected in this example. bool onPacketReceived(const PeerId, const Packet&, const ChannelId) { //todo: Do something with the packet. return true; //@todo Explain return value. } ... packetConn->setReceivePacketCallback( &onPacketReceived );
Example 2 : Member function callback
using namespace net; // No namespace collisions expected in this example. struct Receiver { bool onPacketReceived(const PeerId, const Packet&, const ChannelId) { //todo: Do something with the packet. return true; //@todo Explain return value. } }; ... Receiver receiver; packetConn->setReceivePacketCallback( boost::bind(&Receiver::onPacketReceived,&receiver,_1,_2,_3) );
By default when using callbacks the callback is run from within the/a networking thread. This may induce synchronization issues.
There's an alternative which can be used to avoid this easily. In this case, the connection object collects received packets until the application decides to request them. The application has to trigger the execution of the callbacks, the execution happens in the calling thread (e.g. application).
It works like this:
// Set callback packetConn->setReceivePacketCallback( &onPacketReceived ); // Enable manual callback trigger: packetConn->setManualCallbackTriggerEnabled( true ); // Call this whenever you want to handle received packets: packetConn->handleReceivedPackets();
The call to handleReceivedPackets() does not block the network for the duration of the packet callbacks. It just blocks it for a very short time to get access to the packet queue.
The following example sends a 16-bit unsigned integer using default settings (i.e. reliable, ordered delivery on channel 0):
net::uint16 data = 0x4a4a; packetConn->send(&data, sizeof(net::uint16));
The following example sends a 16-bit unsigned integer (i.e. 2 bytes) on channel 5 using unreliable, unordered delivery.
using namespace net; // no namespace collisions expected in this example uint16 data = 0x4a4a; packetConn->send(&data, sizeof(uint16), TransportSettings().channel(5).ordering(O_ORDERED).reliability(R_UNRELIABLE));
What happens is that a temporary TransportSettings object is instantiated and modified to hold custom settings. The following code does the same as before but uses a local variable to hold the transport settings.
using namespace net; // no namespace collisions expected in this example TransportSettings settings; settings.channel(5).ordering(O_ORDERED).reliability(R_UNRELIABLE); uint16 data = 0x4a4a; packetConn->send(&data, sizeof(uint16), settings);
Server connections support black and white listing.
To reject a client connection attempt from certain IPs and/or hosts use the black listing feature like this:
std::vector<std::string> hostList; ipList.push_back("192.168.1.33"); ipList.push_back("badserver.whatever.tld"); packetConn->setBlackList( hostList ); packetConn->setBlackListEnabled( true );
Using the white list works the same, you just have to call setWhiteList() and setWhiteListEnabled() instead.
If you activate both methods, black and white listing, the server connection object will consider the 'black list' to be of higher importance.
//@todo