The online racing simulator
TINY_NCN and TINY_NPL
(16 posts, started )
TINY_NCN and TINY_NPL
InSim.txt indicates that if a program sends a TINY_NCN packet, LFS should respond with IS_NCN packets for each connection. Similarly for TINY_NPL, only it should respond with an IS_NPL for each player in the race.

When I send a TINY_NCN (so I can get information about the players already on when the InSim program connects to the server), I only get back an IS_NCN for the host, not for any other connected players. Is that the expected behavior?

If so, is there another way to get IS_NCN packets for all connections with patch X?
Err sending a TINY_NCN and TINY_NPL gets me all players back - are you sure you're not mis-parsing the responses?
Strange..I only get one. Even if I were mis-parsing, which I'm not since it's completely automatic using a slightly modified InSim.txt, I'd still be able to see that I was getting the packets in the first place.

As I mentioned, I get one back when I should get two.


Session LFSW Started
Connected
0x0000 : 04 03 02 0D : ....
0x0000 : 04 03 02 0E : ....
Packet Type: "ISP_NCN"
Packet Type: "ISP_MSO"
Recieved Message from Server:
Type: ISP_MSO
Msg: wierdo^L disconnected

In that particular instance, I shouldn't be receiving any IS_NPLs, since I wasn't actually in the field when the InSim program connected, but I should have received two IS_NCN. (or ISP_NCN as it's printing out there)

Edited to add: IS_NCN works fine if I bring up the InSim program and then connect to the server.
Is this when you're connected via insim to a client, or via insim to the server? I've never tested it on the clientside
Could it be you are reading the TCP receive buffer wrongly?

There's a very common error people make, which is to assume they only receive one packet at a time.

In fact, you can receive any number of packets in a single call to receive data on your TCP socket.

Full details and explanations here : http://www.lfsforum.net/showthread.php?p=439516#post439516
Quote from Scawen :Could it be you are reading the TCP receive buffer wrongly?

There's a very common error people make, which is to assume they only receive one packet at a time.

In fact, you can receive any number of packets in a single call to receive data on your TCP socket.

Full details and explanations here : http://www.lfsforum.net/showthread.php?p=439516#post439516

You caught me; tcpdump proved it.

As you point out in that thread, even if it did work that way, I'd need to be more careful about it, since the InSim packet could be broken up across multiple TCP packets. That's going to be harder to deal with in my case than processing the extra packet already in the buffer. Damn perl!
Yes, scawen, you were indeed right, as proven by my new recv_packet function.

It must be nice always being right.
Great! I'm pleased that's solved.

But I'm not always right!
Keep answering with the same answer Scawen (multiple packets) and you soon will be
The one packet per receive is the one think I like about UDP. The worst thing about TCP receive is that not only can you get more than one packet, you may also get partial packets and you so kind of have to keep a queue of received bytes around. Not sure if that's a scenario that's likely with InSim TCP, because the way each packet is sized they are unlikely to be split up into multiple tcp packets. I just had to deal with that a bunch on larger object serialization that didn't necessarily worry about 4-byte multiples.

That said, I'm still likely to use TCP for all my InSim uses, if for no other reason than the multiple connections. Previously I wrote a single InSim daemon that then used .NET remoting to let my various progs talk over that one connection and that was a pain to debug.
Quote from sdether :The one packet per receive is the one think I like about UDP. The worst thing about TCP receive is that not only can you get more than one packet, you may also get partial packets and you so kind of have to keep a queue of received bytes around. Not sure if that's a scenario that's likely with InSim TCP, because the way each packet is sized they are unlikely to be split up into multiple tcp packets. I just had to deal with that a bunch on larger object serialization that didn't necessarily worry about 4-byte multiples.

That said, I'm still likely to use TCP for all my InSim uses, if for no other reason than the multiple connections. Previously I wrote a single InSim daemon that then used .NET remoting to let my various progs talk over that one connection and that was a pain to debug.

Luckily, it turns out it wasn't too hard to fix..about 15 minutes, but it was nicer with UDP in that I didn't have to think about it at all!

Now I just have to hope that when a partial packet does show up I handled it correctly. :tit:
Quote from nathanm :Now I just have to hope that when a partial packet does show up I handled it correctly. :tit:

I think you can do that easily enough, just test using a very small receive buffer and ask LFS to send you loads of information, like loads of NCN packets or something.

Let's say your buffer is 200 bytes in size and there are 160 bytes in it and LFS tries to sends you a 100 byte packet, but your buffer has only 40 bytes of space, then you will only receive 40 bytes of that packet in your buffer.

Another way to say what I'm saying : The "recv" function has a parameter which is how many bytes you can receive. You can use this parameter to force packets to break up.
Quote from Scawen :I think you can do that easily enough, just test using a very small receive buffer and ask LFS to send you loads of information, like loads of NCN packets or something.

Let's say your buffer is 200 bytes in size and there are 160 bytes in it and LFS tries to sends you a 100 byte packet, but your buffer has only 40 bytes of space, then you will only receive 40 bytes of that packet in your buffer.

Another way to say what I'm saying : The "recv" function has a parameter which is how many bytes you can receive. You can use this parameter to force packets to break up.

I could if I weren't using a very high level library to do the socket code. The closest I get to a socket is telling the library what port to connect to and what function to call back to when it's received some data.

Good thing, too. I once tried my hand at writing some socket code in C many years ago, back before I learned better than to use low level languages (I'm not cut out for them beyond minor modifications!) and all I managed to do was get mad.

Perhaps I could split the buffer up after the callback and pretend. Or I could just hope. (the most likely course of action, by far)
Maybe someone could make a very simple relay system that is purely for testing and what it does is relay all packets to one client and from that client back to LFS. And what it would do is randomly combine packets together and break them up a bit adding some delay between bytes. It's quite a useless relay program but can just be used for testing that InSim programs are robust enough for internet use.
Quote from nathanm :I could if I weren't using a very high level library to do the socket code. The closest I get to a socket is telling the library what port to connect to and what function to call back to when it's received some data.

You should still be fine. Your callback receives an array of bytes or you passed one in and it tells you how many bytes it actually filled up. Either way you now have some bytes to consume. You start walking through the array identifying packets and digesting them. Finally you will either be at the end of the set of bytes or you will reach the end before you got the bytes specified by the Size of the packet. If that happens, you just copy that partial packet into another array and wait for another callback. Then before processing the new bytes, you prepend the new bytes (or in C, create a new array that fits both old ones and copy both into the new one) and process as normal.
That's what I have it doing, in theory. Scawen was mentioning that if I forced the system call to return fewer bytes than would be in the packet, it would verify that my code is working properly. Since I can't do that, I have to either trust that I got it right or send the buffer through a sub to split it up for testing.

At least perl makes the necessary string manipulation easy. As it stands, I just check to see if a flag I set indicates that I already have a partial packet in the buffer. If not, I check the indicated length of the incoming packet against the length of the buffer. If it's the same length, I whistle a tune and magically decode the packet into a nice hash. If it's too short, I get very sad, set the flag, and store what I have and wait for the next callback. If it's too long, I thank my diety of choice for my fortune in having at least one packet to decode and do that, then call my callback function with the remainder of the data so it can figure out what to do with it.

If the flag is set, I unset the flag, prepend the old data onto the new data, and do as above.

It should work, but I make lots of typos. I know the part about having too much data works fine, since it now parses the second packet that came in the same callback that prompted me to start the thread in the first place.

TINY_NCN and TINY_NPL
(16 posts, started )
FGED GREDG RDFGDR GSFDG