irrNetLite 2.1 [BETA]

Announce new projects or updates of Irrlicht Engine related tools, games, and applications.
Also check the Wiki
Post Reply
Scarabol
Posts: 167
Joined: Sat Jan 03, 2009 5:26 pm
Location: Aachen, Germany

Post by Scarabol »

Hi,

im using a 32 bit system, and long is also called long long or 64bit integer, with range from:

Code: Select all

signed long long LLONG_MIN 	-9223372036854775807
					  LLONG_MAX 	 9223372036854775807
Is it possible to set the timeout for server, when he sets the client as disconnected?

Greetings
Scarabol
wITTus
Posts: 167
Joined: Tue Jun 24, 2008 7:41 pm
Location: Germany

Post by wITTus »

Scarabol, use this meanwhile:

Code: Select all

//! Operator extension to IrrNetLite
SOutPacket& operator << (SOutPacket& lhs, const SOutPacket& rhs) {
        const c8* Data = const_cast<SOutPacket&>(rhs).getData();
        size_t    Size = const_cast<SOutPacket&>(rhs).getSize();

        for (size_t i=0; i<Size; ++i)
                lhs << Data[i];

        return lhs;
}
I thought I could design my code in a way that I wouldn't need any further modifications of IrrNetLite, but it was impossible. I had to write a little workaround to peek for the next byte without modifying the read position (no get/setPos for SInPacket):

Code: Select all

Object* CGameManager::makeObject(SInPacket& P)
{
        SInPacket Peek(P);

        ObjectType Type;
        Peek >> Type;

        switch (Type) {
                // Continue use of `P'
Another thing is, that debugging of an incoming packet is hard, because I can't get the byte size of the incoming packet, as there is no getSize() function for SInPacket. So I can only guess how long the char array returned by getData() could possibly be.

@BlindSide: After reading this, I'm wondering if it is save to send stringw between Linux and Windows machines.
Generated Documentation for BlindSide's irrNetLite.
"When I heard birds chirping, I knew I didn't have much time left before my mind would go." - clinko
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

Is it possible to set the timeout for server, when he sets the client as disconnected?
Since I abstracted the Enet interface away, theres really no way of doing it without exposing the interface yourself and recompiling IrrNetLite. Then you can probably adjust a relevant setting directly through the Enet host, as timeouts are handled by it.
Scarabol, use this meanwhile:
Yes that's a good idea for now.
I thought I could design my code in a way that I wouldn't need any further modifications of IrrNetLite, but it was impossible. I had to write a little workaround to peek for the next byte without modifying the read position (no get/setPos for SInPacket):
I'm not sure why you need to do this, once you read the packet type header you can store it somewhere and do whatever you want with it, it sounds like a bad design decision to have to peek at it. But I suppose some kind of Peeking functionality is expected, so I'll add that to the TO-DO list. I should add getPos, maybe setPos too, will have to think about the repercussions of that one.
Another thing is, that debugging of an incoming packet is hard, because I can't get the byte size of the incoming packet, as there is no getSize() function for SInPacket. So I can only guess how long the char array returned by getData() could possibly be.
You're right, this is important. Needs a getSize().
@BlindSide: After reading this, I'm wondering if it is save to send stringw between Linux and Windows machines.
Good point maybe it would be a good idea to send the character size along with the string (Only an extra byte) and use that when decoding.

I appreciate your testing Wittus, after the second revision I thought I had close to a perfect interface (I know that is a laughable statement) because of the simplicity but you have pointed out several shortcomings.

Cheers
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Scarabol
Posts: 167
Joined: Sat Jan 03, 2009 5:26 pm
Location: Aachen, Germany

Post by Scarabol »

Hi,

why is this possible?

Code: Select all

net::SInPacket packet;
net::SOutPacket packet; //other data types create a debug error here :-(
I implemented IrrNetLite in my current project and have to say that u did a very good work so far. Thanks a lot!

Greetings
Scarabol
wITTus
Posts: 167
Joined: Tue Jun 24, 2008 7:41 pm
Location: Germany

Post by wITTus »

BlindSide wrote:I'm not sure why you need to do this, once you read the packet type header you can store it somewhere and do whatever you want with it, it sounds like a bad design decision to have to peek at it. But I suppose some kind of Peeking functionality is expected, so I'll add that to the TO-DO list. I should add getPos, maybe setPos too, will have to think about the repercussions of that one.
Well, maybe you could implement it somehow in a const way, so that it won't change the packet. I'll tell you why I probably (I'm not 100% sure though) need that.

I store lots of different information in one single packet. The sender "tags" the packet with an one-byte identifier, appends data, tags, appends data and so on. When the packet gets finally sent, the client receives it, and would firstly check which identifier it got and pass the SInPacket to the correct program modules. No problems here, till now. (Except that if one module is misbehaving, the whole chain breaks - which looks like a hint for bad design for the whole approach... :roll:)

But then, I'm sending information for units. This contains the unit type, unit ID etc. Now I have the dilemma of letting initialise the unit itself simply by giving the packet to its constructor (which is very handy) - or I initialise an half empty unit object each time and call something like Obj->setType(t); after the switch(t) { } statement, which is more dangerous. I decided for the former solution, but there I need to peek the unit type.
BlindSide wrote:Good point maybe it would be a good idea to send the character size along with the string (Only an extra byte) and use that when decoding
Two possibilities. At first I thought about sending a byte which contains several flags for special behaviour of irrnet. But then I thought that maybe other machines could use completely different sizes for wchar_t as well. I'm not sure yet. But sending it once at the beginning of the packet is definitively the best way respectively.
Scarabol wrote:why is this possible?

Code: Select all

net::SInPacket packet;
net::SOutPacket packet; //other data types create a debug error here :-(
Why would someone want to do that??? And no, it's not possible. There's no default constructor for class SInPacket anyway... :lol:
Generated Documentation for BlindSide's irrNetLite.
"When I heard birds chirping, I knew I didn't have much time left before my mind would go." - clinko
Nox
Posts: 304
Joined: Wed Jan 14, 2009 6:23 pm

Post by Nox »

wchar_t is 2 bytes under windows and 4 bytes under *nix 64bit :). Well i handle this issue by setters for the read and write offsets in my bitstreamclass. So specific peek method is not really a good thing at all, i guess.
Jesterstear
Posts: 18
Joined: Mon Jan 19, 2009 9:14 pm

Post by Jesterstear »

Well, I looked through the posts on here and might have found the answer to my problem, but am still unsure.

I was creating my server and when I would run it, there would be a Break whenever a message was received by the server.

I thought maybe it was my code, so I copied over the example and sure enough the same error occurred.

The break is in CNetManager.cpp on line 217

Code: Select all

											<< event.peer->address.port << std::endl;
I get messages like "A message has been received from player 1" when I do not try to output my message.
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

Well what is the answer to your problem?

I would focus on getting that example to run first. What operating system and architecture are you using?

REMEMBER: Provided MSVC lib is _incompatible_, it was built before I made some header changes, so you have to rebuild it yourself.

When I find the time I will release a non-beta version that has a useful lib file.
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Jesterstear
Posts: 18
Joined: Mon Jan 19, 2009 9:14 pm

Post by Jesterstear »

Well the solution I found was copying and pasting the source into my project, but I think that was for a linking issue.

I am on Windows XP 32-bit.

And it is not a linking problem, I built everything myself.

EDIT: Alright, I found the problem.

Thanks for the irrNetLite!

EDIT2: Alright, well, it was working.
Then I added in

Code: Select all

std::cout << str.c_str();
And I am getting the same exact error....

EDIT3: Ugh never mind, the examples work, which means that there is something with the tutorial.
I'll learn from the examples instead :wink:

EDIT4: Ok, I give up, now the Example2 errors on a completely different line.
wITTus
Posts: 167
Joined: Tue Jun 24, 2008 7:41 pm
Location: Germany

Post by wITTus »

BlindSide wrote:
@BlindSide: After reading this, I'm wondering if it is save to send stringw between Linux and Windows machines.
Good point maybe it would be a good idea to send the character size along with the string (Only an extra byte) and use that when decoding.
Problem confirmed. :?
Are you still working on this? I'd like to see an update :wink:
Generated Documentation for BlindSide's irrNetLite.
"When I heard birds chirping, I knew I didn't have much time left before my mind would go." - clinko
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

Thanks for the reminder, I have been extremely busy lately. I hope to get some time later this month.

Aside from the character encoding fix, is there anything else you're looking forward to/wanting to see implemented?

I was thinking either A. Synchronized state objects. B. File transfer.

On another note I uploaded some precompiled libs for people that need them (See first post, read warning carefully).

Cheers
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
wITTus
Posts: 167
Joined: Tue Jun 24, 2008 7:41 pm
Location: Germany

Post by wITTus »

- Provide precompiled packets asides from the source only tarball
- Don't make it Irrlicht independent (the more code is outsourced the better; that's only a proposal but at the end it's up to you)
- operator << (SOutPacket&) for class SOutPacket
- peek functionality for SInPacket (not absolutely necessary, can be implemented by the user which is probably better but should be mentioned in the documentation, though)
- getSize() for SInPacket !
- wchar_t size fix (maybe as a simple one-byte bit-flag, transmitted when the netmanagers do their initial handshake? would enable us 7 other boolean switches for further changes)
- make getSize() const
- add a const correct version of getData()
- Synchronized state objects (your proposal)
- file transfer (your proposal)

Phew. More than I thought :wink:
Generated Documentation for BlindSide's irrNetLite.
"When I heard birds chirping, I knew I didn't have much time left before my mind would go." - clinko
Ion Dune
Posts: 453
Joined: Mon Nov 12, 2007 8:29 pm
Location: California, USA
Contact:

Post by Ion Dune »

I'm having a bit of a problem with one of the network systems in my games. I'm troubleshooting, and I just have a couple of IrrNetLite/general networking questions:

1) Is it possible for packets to be received in an order other than they are sent? My host sends a game description out to clients whenever they connect, and I've got a problem where the client will receive packets pertaining to a game they haven't received details about yet. So it would seem that the packets sent using the OnConnect callback are being received after packets sent at other times. Is this possible? I would have thought that OnConnect() would be called by the host before a new user started receiving packets, or is this not the case?

2) Is it foolish to have a system that relies integrally on every packet being delivered successfully, or should I take into account the possible that data may be lost?

Thanks for your time!
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

irrNetLite is based on enet, which is based on UDP.

Now Enet does technically provide a reliable layer similar to TCP over UDP but packets may still be dropped. They are also not guaranteed to be in order.

This was a conscious decision of course, as a lot (But not all) of game network content would benefit from this approach, since TCP usually provides too much overhead for things like sending player positions, etc (Things where the most recent packet is needed, and the older packets can be discarded). With irrNetLite, sendOutPacket() should provide reliable delivery of packets (But not in-order delivery). When you don't care about reliability and want to save on bandwidth you can use sendOutPacketUnreliable() which doesn't bother resending packets if their not received.

Now to answer your questions:
1) Is it possible for packets to be received in an order other than they are sent? My host sends a game description out to clients whenever they connect, and I've got a problem where the client will receive packets pertaining to a game they haven't received details about yet. So it would seem that the packets sent using the OnConnect callback are being received after packets sent at other times. Is this possible? I would have thought that OnConnect() would be called by the host before a new user started receiving packets, or is this not the case?
Yes, it is possible. What I recommend you do is combine these 2 packets into a single packet. Then you would have all that information in the intended order. Is there a reason that is not practical? Enet can take any packet size and split it up into smaller packets then join it again, so packet size is not usually an issue unless it is so big that it would eat performance (Anything under 10kb should be fine).
2) Is it foolish to have a system that relies integrally on every packet being delivered successfully, or should I take into account the possible that data may be lost?


Not foolish, this is what TCP is for. Like I said earlier you may be better off combine sequential data into the same packet, then you are guaranteed to receive it in the same order. If you are sending packets so close together that the later one would arrive before the other then I guess you would have no problem with just combining them into the same packet.

Cheers

EDIT:

Waaait a second... the Enet website says this:
ENet provides sequencing for all packets by assigning to each sent packet a sequence number that is incremented as packets are sent. ENet guarentees that no packet with a higher sequence number will be delivered before a packet with a lower sequence number, thus ensuring packets are delivered exactly in the order they are sent.

For unreliable packets, ENet will simply discard the lower sequence number packet if a packet with a higher sequence number has already been delivered. This allows the packets to be dispatched immediately as they arrive, and reduce latency of unreliable packets to an absolute minimum. For reliable packets, if a higher sequence number packet arrives, but the preceding packets in the sequence have not yet arrived, ENet will stall delivery of the higher sequence number packets until its predecessors have arrived.
So apparently Enet does guarantee sequenced delivery. We may be running into this issue: http://lists.cubik.org/pipermail/enet-d ... 00746.html

Before I make the next release I'll run some tests and see if there's anything weird going on. This'll have to wait as I have exams this coming week and the next.
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Nox
Posts: 304
Joined: Wed Jan 14, 2009 6:23 pm

Post by Nox »

Now Enet does technically provide a reliable layer similar to TCP over UDP but packets may still be dropped. They are also not guaranteed to be in order.
You already corrected it. And here are the flags :) :
/** packet must be received by the target peer and resend attempts should be
* made until the packet is delivered */
ENET_PACKET_FLAG_RELIABLE = (1 << 0),
/** packet will not be sequenced with other packets
* not supported for reliable packets
*/
ENET_PACKET_FLAG_UNSEQUENCED = (1 << 1),
/** packet will not allocate data, and user must supply it instead */
ENET_PACKET_FLAG_NO_ALLOCATE = (1 << 2)
By the way. TCP is not bad at all. I dont understand why people try to implements a own TCP over the lightwight UDP. Do you really think that using a racingcar as a base for a familycar is a good idea? Of course the original racingcar is faster but with a hanger for the package it is not really fast anymore, is it?
If you are interested just take a look at http://irrlicht.sourceforge.net/phpBB2/ ... hp?t=33015 . In these testcases tcp is not really worse in performance. Im still searching for a way to measure the generated traffic too. I guess one reason why many people think that TCP is worse is the nagle-ack issue. But this can be fixed by disabling the nagle algo which tries to collect small packets and put them in one big packet.
Post Reply