• Welcome to Valhalla Legends Archive.
 

[C/Linux] Server Model, need help

Started by rabbit, June 14, 2007, 12:45 PM

Previous topic - Next topic

rabbit

I'm writing a fairly simple server for chatting, mostly for fun and just to learn how to make something like this.
Right now, I'm thinking about something like this:


Basically, I have the main body with all the intialization and stuff of that nature.  Elsewhere, I've got configuration handlers for loading/saving the configuration files; a settings system (mostly what I need help with); a data buffering system; and incoming and outgoing parsers (easy parts to make, still need a little help).

Basically, red arrows are raw data coming in, green arrows are links between parts of the program, and blue are necessary links I can't think of a way to describe concisely.  Basically, my problem is that I suck at C.  I want my config handlers to be able to modify variables in settings, though I'm not sure how to do this.  Wrappers, direct edits, what?  Also, how would my parsers be able to use variables and such from the settings portion?
Grif: Yeah, and the people in the red states are mad because the people in the blue states are mean to them and want them to pay money for roads and schools instead of cool things like NASCAR and shotguns.  Also, there's something about ketchup in there.

Barabajagal

Use either global variables, or public functions that are just Get and Set of the variables you need to use publicly?

rabbit

I've always had trouble using global variables.  I'm not sure why.  Whenever I've used them in the past I've gotten errors about unknown variables and the such.  Always a pain.  I don't really want to use a wrapper, but if I have to I will..

[edit]
It appears that it's because I haven't been using extern...okay :D
Grif: Yeah, and the people in the red states are mad because the people in the blue states are mean to them and want them to pay money for roads and schools instead of cool things like NASCAR and shotguns.  Also, there's something about ketchup in there.

iago

Using extern is generally evil. It should be avoided whenever possible.

Settings might be an exception for it. The way you should implement it is by putting the variable itself in a .c file, and the "extern" in the corresponding .h. That way, whenever something includes the .h file for the module, it gets access to that variable.
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


Banana fanna fo fanna

Just have ONE global variable called "gApp" which is a struct containing every global that you would need (including config settings).

The scariest part, which you haven't dealt with, is the concept of time (which is one of the scariest concepts in computing). How are you going to handle talking to multiple connections? Threads? Pseudo-threads? Nonblocking I/O? Callbacks?

rabbit

Well, Linux makes it much easier to multi-thread (fork() vs CreateProcess(1 billion args)), but I've also been looking at nonblocking I/O.  This is going to be a small server, with a user cap of maybe 100-200 connections.  I haven't decided on how I'm going to handle that stuff yet because I don't know much about it.  Suggestions on that?
Grif: Yeah, and the people in the red states are mad because the people in the blue states are mean to them and want them to pay money for roads and schools instead of cool things like NASCAR and shotguns.  Also, there's something about ketchup in there.

iago

Figure out how to use select(). You can do a select() across any number of outgoing sockets and incoming sockets, as well as stdin.

If you want a demonstration of using select() for a chat server/client, let me know. I have one uploaded somewhere that wrote for school. I could find it if you want.
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


rabbit

That would be awesome :D

All the stuff I've been reading about select is kind of vague, and the code is weird :\
Grif: Yeah, and the people in the red states are mad because the people in the blue states are mean to them and want them to pay money for roads and schools instead of cool things like NASCAR and shotguns.  Also, there's something about ketchup in there.

Banana fanna fo fanna

forking is NOT a good way to go. The One True Way to write networked applications (IMO) is a few worker processes (or real OS threads) which use non-blocking I/O to process everything (I believe this is how Apache does it). Usually, one process/thread per processor core is a good idea.

rabbit

So then maybe 1 thread for the socket, another for the data parsing, and a third for everything else?
Grif: Yeah, and the people in the red states are mad because the people in the blue states are mean to them and want them to pay money for roads and schools instead of cool things like NASCAR and shotguns.  Also, there's something about ketchup in there.

iago

http://www.javaop.com/~ron/code/cc.tgz

Unless you're doing heavy processing, you only need 1 thread with non-blocking i/o (or using select()). CattleChat (nickname for the project) has a server and a client, both with a GUI (curses, text-based) and with exactly one thread each.

One thing you might find interesting is that I based my protocol on Battle.net, so it's a pretty good framework if anybody wants to hollow it out and change the packets to BNET ones. But that's neither here nor there. There's no license on this, it was a school project and I'm calling it public domain.
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


Banana fanna fo fanna

Best thing (IMO) is to have an I/O thread that is ONLY responsible for reading (and perhaps parsing) incoming data and stuffing it along with a client identifier (ip/port combo or socket handle) into a queue. It also reads from the outgoing data queue and does the appropriate I/O there as well. You can then have X worker threads in a pool waiting on that queue to actually act on that data. BE VERY CAREFUL ABOUT THREAD SYNCHRONIZATION. If you are careful about locking (or you just use message passing, perhaps with the queue), you should be alright.

To maintain client state, you're going to have a lookup table that maps a client ID (again, ip/port or handle) to a struct containing any data you need (is_logged_in, username, current_channel, etc).

Trust me, I know what I'm doing. This is the best way to do it. Why? When I said you can add X threads, it means you can just add more and more processors and, depending on how much shared state you have, your system will scale to more users. With multicore systems coming into play more and more, you're going to have to learn this eventually; learn it now. Sure, you could probably get away with just one thread for everything (or even one thread per client!), but that's not the right way to do it.

Do you know about proper locking techniques and what it means to have as little shared mutable state as possible? I love this stuff, and teaching someone else helps me learn more myself!

rabbit

I have no clue!  Please, teach me :D

I've always wanted to make a simple chat server of my own, but all attempts have thus far ended in tragedy: VB6, C, C++, and Java.  I got farthest in Java with data parsing and packet building, but nowhere with users.  In C and C++, I got all my file handling done pretty well, but nothing else.  My VB one actually was a full blown server, except it was prone to crash and was in VB.  BAH!

I really want to write some quality stuff this time.  It'd be great if you and Ron would help me out.
Grif: Yeah, and the people in the red states are mad because the people in the blue states are mean to them and want them to pay money for roads and schools instead of cool things like NASCAR and shotguns.  Also, there's something about ketchup in there.

Banana fanna fo fanna

OK. Start at the beginning. Write an echo server: listens on a TCP port, accepts a connection, and whatever data it receives it sends back out. Do it with one thread and select() and nonblocking I/O. gogo~

rabbit

#14
I'll get right on it!

An iago, could you please allow traffic through port 9933?  That'd be awesome.

select(): http://pastebin.com/930219
Grif: Yeah, and the people in the red states are mad because the people in the blue states are mean to them and want them to pay money for roads and schools instead of cool things like NASCAR and shotguns.  Also, there's something about ketchup in there.