The online racing simulator
Discussion from "Guide: My first InSim Application"
Good job Karl, way to start this up
Thank you very much! I have some remarks:
- What is the licence of your code? I bet, that it's public domain, but it should be mentioned somewhere.
- There is a nice c++ sockets library (under GPL, _not_ LGPL though), so no need to do TCP buffering job in a real project. I understand, that for tutorial application is better to have all the code in one file.
- Some flowchart could be helpful, if you would spare time to create it :-).

/*the rest of the text can be safely ignored*/
I have also pedantic comment to the coding style used in the tutorial (and in many program sources here). The 'else' keyword is used very often and unsuitable. It causes the indentation of the code to grow over 10th level.. E.g.:
while (ok > 0) {
if (test() == FAILED) {
ok = -1;
} else {
<a very long program on indent level #2>
if (some_other_test() == FAILED) {
ok = -1;
} else {
<a very long program on indent level #3>
....
}
}
}

Compare it with the following:
while (ok > 0) {
if (test() == FAILED) {
ok = -1;
continue;
}
<a very long program on indent level #1>
if (some_other_test() == FAILED) {
ok = -1;
continue;
}
<a very long program still on indent level #1>
}

Actually, there are only a few cases in a real program, that require the 'else' keyword. In my example, I should use the 'break' keyword instead of 'continue', because the loop breaks at the point. But the test '(ok > 0)' could be more complicated.

Thank you again for your effort , please don't bother too much about my coding style pedantry .
One word, Semantics.

The use of ... (Do I really want to post this? Will it start just another one of those threads, where we discuss the pros and cons of one style of programming over another, have we not beaten that horse to death yet? No apparently not) ... the else statement in the code is a good start for beginners to look at. Indeed, most people who will be looking at this code will be beginners. I don't disagree that the style you brought up is good, but people might not get it right away, where as the if else style kinda lends it self to a more obvious flow.

Simply put, it's easier for noobs to understand. Now could we please get off this topic, and back ON TOPIC?
-
(mcgas001) DELETED by mcgas001
Quote from Kada_CZ :- What is the licence of your code? I bet, that it's public domain, but it should be mentioned somewhere.

Yes, I should've put a licence on it. I will do shortly.

Quote from Kada_CZ :- There is a nice c++ sockets library (under GPL, _not_ LGPL though)[/url]

Which is ok, as long as you're using a C++ compiler

Quote from Kada_CZ :- Some flowchart could be helpful, if you would spare time to create it :-)

Agreed, I was planning on replacing the "text based" flowchart in the abstract post, with a decent graphical one At Some Point(TM), so this'll push me to do it sooner, unless anyone else fancies producing one first.

Quote from Kada_CZ : /*the rest of the text can be safely ignored*/

As if you can get away with that!

Quote from Kada_CZ :I have also pedantic comment to the coding style used in the tutorial (and in many program sources here). The 'else' keyword is used very often and unsuitable. It causes the indentation of the code to grow over 10th level..

...

Compare it with the following:

...

Actually, there are only a few cases in a real program, that require the 'else' keyword. In my example, I should use the 'break' keyword instead of 'continue', because the loop breaks at the point. But the test '(ok > 0)' could be more complicated.

I totally agree, the reason for the crappy styling is due to the fact it was mostly ripped out from the publically available versions of luaLFS (), and to make it a bit more obvious what's happening - you'd be surprised how many people have a brain fart when they see a "continue;" statement

Quote from Kada_CZ :please don't bother too much about my coding style pedantry .

I really, truely appreciate any and all comments; I feel that I should learn stuff every day, and if what I learn is how to code better (because quite frankly I'm not a wizard and I don't produce perfect code, although I do have a bit of a knack of hacking stuff together, so if we can do anything to improve readability and/or the quality of any of the tutorials/example code, then lets go for it)! Lets keep them coming!

I seriously mean this guys, I really do like constructive criticism - equally though there are plenty of times you can just tell people that they're talking bollocks If you want to replace or provide an alternative set of code, or tutorial, then please feel free to provide it.

Over time I plan to tidy up the programmers bit on the wiki/manual as well, and merge whatever comes out of this, so hopefully we can get a set of really nice documents!

I'll add a link to this thread, from the guide, and where appropriate merge and/or replace stuff over time.
Quote from Dygear :the else statement in the code is a good start for beginners to look at. Indeed, most people who will be looking at this code will be beginners. I don't disagree that the style you brought up is good, but people might not get it right away, where as the if else style kinda lends it self to a more obvious flow.

Simply put, it's easier for noobs to understand.

It's not, from my point of view, because the code with indent level 10 is unreadable.

Quote from the_angry_angel :I totally agree, the reason for the crappy styling is due to the fact it was mostly ripped out from the publically available versions of luaLFS (), and to make it a bit more obvious what's happening - you'd be surprised how many people have a brain fart when they see a "continue;" statement.

I teach beginners here at university. So I know, that some of them has problems to discover, how to use 'break' and 'continue' (and 'return') correctly. But they should learn these statements from the beginning, I think. A beginner should see the right coding style in a tutorial.

I rewrite the_angry_angel's code according to my notions, see the attachement. Warning: I did not test the code!
Attached files
main.c.txt - 11 KB - 312 views
#6 - sun
hi,

Thanks for that.

i have to say but '-=STG=- City Cruise' are saying that that insim is theres and that one of them made it, but its just downloaded off the forum.

Just thought i would tell you.

I downloaded the file, but i edited it and it says who made it so really its like 50 50.

Thanks for that Karl

its taught me a heck of alot...
EDIT: The previous question was deleted because I found an answer myself, this is new

I'm going all the way through this C tutorial before looking for a sockets library in order to understand all the process and I have some thoughts:

int retval = recv(s + 1, tbuf + bread, PACKET_BUFFER_SIZE - (unsigned int)bread, 0);

Why do you use the "socket_file_descriptor + 1"? In the reference I've seen you have to use the socket file descriptor as the first parameter, so I don't know why the "+1". Can anyone explian this to me?

More stuff:

int ok = 1;
while (ok > 0)
{
int rc;
// Set the timeout period
struct timeval select_timeout;
select_timeout.tv_sec = IS_TIMEOUT;
select_timeout.tv_usec = 0;

// Setup the file descriptor watches
fd_set readfd, exceptfd;

// Clear them
FD_ZERO(&readfd);
FD_ZERO(&exceptfd);

// Set them to watch our socket for data to read and exceptions that maybe thrown
FD_SET(s, &readfd);
FD_SET(s, &exceptfd);
...
}

All this stuff at the beginning of the main loop could, and in my opinion *should* be taken out of the while. I think the FD_SETs and the timeval struct are defined once and then they keep using the same values during the while, so there's no need to keep that inside.

Another thing I've noticed is that you declare many vars inside the main loop. Those vars get declared and deleted in every iteration. I think those declarations could be made outside the while, making a reference to what they're going to be used to in a comment.

More stuff:
while ((PACKET_BUFFER_SIZE >= (tbytes - bread - (unsigned char)*p)) && ((tbytes - bread - (unsigned char)*p) >= 0) && ((unsigned char)*p > 0))

This is the main while. The condition there... I don't understand the first part:

PACKET_BUFFER_SIZE >= (tbytes - bread - (unsigned char)*p)

Taking a look at the code, "tbytes" max value can be "PACKET_BUFFER_SIZE" (unless i've missed something). So "tbytes - anything" will always be lesser or equal to PACKET_BUFFER_SIZE. In my opinion that condition is always true and therefore can be taken out. I understand the other two parts of the whole expression, but this first part I don't see any sense in it.


I'll report more things like these if I notice anything suspicious
I'm afraid I'm away from my home office for a few days, on company business and my laptop has died I'll be back in a few days - if I have the opportunity to tap out a response before then, on a computer I can use for personal stuff, I'll pop it in.
Another new thing I've noticed:

An IS_TINY is sent as a "version packet". There's no checking the version after this. I mean, the version request is sent but the IS_VER packet returned by insim is not processed in any way.

Another thing is that in the current insim version (4) you can request the IS_VER directly in the IS_ISI setting ReqI to non-zero, there's no need to create a whole IS_TINY for that purpose if you are just checking right after the IS_ISI is sent -which is the case-.
Quote from MaKaKaZo :why the "+1". Can anyone explian this to me?

Under unix-like OS' the socket argument is "the highest numbered file descriptor, plus 1". On Windows this doesn't matter too much in my experience (most likely because I believe that the berkeley functions eventually fall back to the WSA stuff), although it does else where (see any man page for select, to explain why it should use the highest fd + 1).

Quote from MaKaKaZo :All this stuff at the beginning of the main loop could, and in my opinion *should* be taken out of the while. I think the FD_SETs and the timeval struct are defined once and then they keep using the same values during the while, so there's no need to keep that inside.

The FD sets and timeval struct must be reset at each loop, the reason being that you always need to zero the fd sets to ensure you're getting data that's relevant for that select() query. It is up to the programmer to ensure that the memory is clear, select() does not do that.

The timeval struct also needs to be reset each time, because select() can and will modify it. You could delcare it outside, but I'll explain my rational below

Quote from MaKaKaZo :Another thing I've noticed is that you declare many vars inside the main loop. Those vars get declared and deleted in every iteration. I think those declarations could be made outside the while, making a reference to what they're going to be used to in a comment.

That's a tiny implementation detail. I could've done the entire thing about 5 different ways..? The only difference that you've missed is that you need to ensure the relevant variables are zero'ed/cleared again.

Something I didn't make clear, but perhaps should've was that the tutorial was hacked together from the start of libLFS, which was itself ripped out of luaLFS, which itself was ripped out of another insim v4 project, which itself was ripped out of an insim v3 project that was written years ago - it's never been completely cleaned up since. It's not perfect, and I'm happy to admit that, but what you're picking up on here is a matter of taste. Once the loop iterates over the fact that they're redeclared is irrelevant, although some body new to C might say that it's easier to understand in the current format (because, quite frankly if someone knows the basics of C, and can read a man page, I can't see them needing this example).

Quote from MaKaKaZo :PACKET_BUFFER_SIZE >= (tbytes - bread - (unsigned char)*p)

You're probably right, but I've literally got in 30 minutes go, so I don't know off the top of my head. I'll check it out tomorrow morning after I've had my coffee and a good night's sleep

Quote from MaKaKaZo :An IS_TINY is sent as a "version packet". There's no checking the version after this. I mean, the version request is sent but the IS_VER packet returned by insim is not processed in any way.

I had thought I'd made that clear in the comments already? (again, I've not checked, I've not had the opportunity).

Quote from MaKaKaZo :Another thing is that in the current insim version (4) you can request the IS_VER directly in the IS_ISI setting ReqI to non-zero, there's no need to create a whole IS_TINY for that purpose

Yes, but there are 2 reasons here;
1. As I've already explained when the underlying code was originally written (years ago now) that didn't exist in insim
2. It's an example of how to send a packet, which if I recall isn't given else where in the code

At the end of the day it's a really rough example, like most other code in that thread so far. If anyone wants to replace what's already written then I'm more than happy to remove posts in favour of theirs. If it were perfect then you'd see things like the global buffer, socket fd, etc. put into a central struct, the entire code modularised into functions and so on. But then it wouldn't be an example - it would be a library
Thank you very much for your answer Karl

As I've spent more and more time studying the code of that example I've come to realize that it was made from several pieces of code as you say.

Your answers have clarified my mind and I hope that I can get my library to work today. Yesterday when I finished it didn't work, the select() calls returned either several timeouts or directly an error.

Only one thing that you've misunderstood in your response:

I ask about the use of "socket_file_descriptor + 1" in the recv() call, not in the select() call. I had already checked the man pages for both of them, and I already understood that for select() you must use "the max file descriptor + 1", but I haven't found anything about that for recv(). I have also checked Microsoft's Winsock2 Reference for recv(). If I get my code to work then I'll try changing it, but until then I'll keep the +1 as it works in the original example.

When I finish this stuff I'll probably release it as an example/tutorial for people to laugh at my code

EDIT: By the way, I was recommended Beej's Guide to Network Programming as an introduction to programming with sockets. I found it quite useful. Anyone knows about any other good tutorial out there?
Hello all,

could someone tell me why I get an "Connection refused forcefully" error with Winsock while trying to connect to my InSim (29999, yes, I'm sure I configured it in LFS) port. I'm using TCP, ofcourse. I tried different ports in LFS, turning my Windows XP SP2 firewall off - nothing.

Got similar (or same) error with DarkTimes' C# .NET example.

FGED GREDG RDFGDR GSFDG