Two player game, forking & sockets


 
Thread Tools Search this Thread
Top Forums Programming Two player game, forking & sockets
# 1  
Old 06-06-2011
Two player game, forking & sockets

Hi.
I am just making first steps in Linux POSIX programming. I have read some tutorials on processes, signals and sockets (thanks Beej!), so some basic knowledge I have already got.
I want to write some very basic game server. My idea is to have main process, which is waiting for new players. If there are at least two clients connected, spawn one process per every player and then start doing some actions (not relevant now). Players (separate processes) would communicate in pairs through hm... I don't know yet, for sure some IPC structure.

According to this very general approach (I am just beginner Smilie) I have few questions:
1. How to provide proper waiting for players, for example when there is no clients at all or there is only one and waits for opponent?
2. How to handle three way inter-process communication? I mean between main process, player1 process, player3 process. I am guessing I would have to use some semaphores.
3. How to handle such communication, when the main process has to gather some information about paired clients moves and waiting for new clients at the same time? Can it be done in one, main process?
4. Could you explain me some basic algorithm how such program should be properly constructed? Some skeleton, names of functions, which manuals I have to study and general hints in order not to make steps blindly.

Thank you in advance.

Last edited by Shang; 06-06-2011 at 02:11 PM..
# 2  
Old 06-06-2011
Quote:
Originally Posted by Shang
Hi.
I am just making first steps in Linux POSIX programming. I have read some tutorials on processes, signals and sockets (thanks Beej!), so some basic knowledge I have already got.
I want to write some very basic game server. My idea is to have main process, which is waiting for new players. If there are at least two clients connected, spawn one process per every player and then start doing some actions (not relevant now). Players (separate processes) would communicate in pairs through hm... I don't know yet, for sure some IPC structure.
Unless they're all on the same machine, it'd pretty much have to be sockets.
Quote:
According to this very general approach (I am just beginner Smilie) I have few questions:
1. How to provide proper waiting for players, for example when there is no clients at all or there is only one and waits for opponent?
Print 'please wait' and block on accept() waiting for more connections? If that's not what you mean please explain in more detail.
Quote:
2. How to handle three way inter-process communication? I mean between main process, player1 process, player3 process. I am guessing I would have to use some semaphores.
It also depends what information's being communicated in what manner.
Quote:
3. How to handle such communication, when the main process has to gather some information about paired clients moves and waiting for new clients at the same time? Can it be done in one, main process?
Sure. You could do different things in different threads, for example.
Quote:
4. Could you explain me some basic algorithm how such program should be properly constructed? Some skeleton, names of functions, which manuals I have to study and general hints in order not to make steps blindly.
We don't have enough information to help you yet. Certainly there's many ways to get what you want.
# 3  
Old 06-06-2011
You are right, I have not told too much.
First I would like to say that this is only my startup program, which may or may not grow into something more clever Smilie I am familiar with object oriented programming, now I want to bite some Unix-like stuff, so here I would like make some research before I mess up the design.

To clarify my idea let me describe example scenario.
There is a server, at the beginning main process only, listening for connections (SOCK_STREAM). There is also client application, may be even telnet or something very simple. It connects to the server.
Server spawns new process for every client connection. If there is enough clients to create some pairs I would like server to pair them somehow (that is tricky for me now). Every process communicates through sockets with its own client somewhere and with the other process. Game is played in turns and its state is being sent to clients on every change. At the server side, main process has to collect somehow states of every game and hmm.. store it, not relevant now.
To provide a better view of what I am going to do I have prepared some scheme (see attachment).
I hope that would clear more my crazy ideas Smilie
Dotted lines means read/write.
Two player game, forking & sockets-schemejpg

Last edited by Shang; 06-06-2011 at 03:24 PM..
# 4  
Old 06-06-2011
Okay.

You can create a shared memory segment with mmap. You can map in a file so as to keep memory stored on disk, or just map it in anonymously. It all just acts like memory either way.

Code:
// file-backed
int fd=open("filename", O_RDWR|O_CREAT);
ftrundate(fd, length);
char *mem=mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);

// not file-backed
char *mem=mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);

Semaphores will work fine to control it. pthread mutexes will work too, at least in modern linux, but semaphores would be more portable.

The server would do something like this very sketchy code
Code:
char *shared_mem;
sem_t sem;

void child_stuff(void)
{
        while(1)
        {
                sem_wait(&sem);
                shared_mem[0]++;
                sem_post(&sem);
        }
}

int main(void)
{
       shared_mem=mmap(...);

       // Initialize shared semaphore to 1.  It can be locked once, further attempts
       // will block.
       sem_init(&sem, 1, 1); 
       while(1)
       {
               pid_t pid;
               int fd=accept(...);
               if(fd < 0) continue;

               pid=fork();
               if(pid == 0) // child code
               {
                       // A forked process gets a copy of everything the main process
                       // has open.  99% of it the child probably doesn't need, so
                       // close it.
                       //
                       // You can also set files auto-close fork with an ioctl, look for 
                       // close-on-exec.
                       close_positively_everything_except_what_child_needs;
                       child_stuff();
                       exit(0); // DO NOT FORGET!  Don't want child doing parent stuff after child_stuff finishes for some reason
               }
               else if(pid > 0) // parent stuff
                      add_to_list_of_children(pid);
               else
               {
                       perror("fork failed for some reason");
                       break;
               }
       }
}


Last edited by Corona688; 06-06-2011 at 04:10 PM.. Reason: many edits to make code slightly less sketchy
# 5  
Old 06-07-2011
Thanks! Now I think that would give me some kickoff. I'll be back if any question arises.

---------- Post updated 07-06-11 at 08:41 PM ---------- Previous update was 06-06-11 at 09:06 PM ----------

As promised, I am back with questions Smilie I have read about different approaches and decided to use SysV shared memory for a start.
First problem:
Assuming that we don't know how many clients(c) will connect and how many games(floor(c/2)) will be started the question is how to manage this shared memory segment?
My first idea was to create an array of pointers to game_state (type, see below), which would be the argument for shmat() function and store information about all games.
But how to dynamically expand this array in case of new game start without ruining attachment? I mean that when we malloc new, bigger amount of memory and freeing old one, the addresses changes. To be honest I have feelings that this idea is useless.
Code:
typedef struct {
    int player_ids[GCOUNT];    // array with player ids
    char board[BOARD_SIZE][BOARD_SIZE];    // 10x10 game board
    char moves_sequence[TILES_NUM];    // array containing information who did what move
    player_stat player_stats[GCOUNT];        // point to a structure containing information who has how many points
} game_state;

Second problem:
How to implement reading and modification of shared memory segment in turns? (player1-mainprocess-player2-mainprocess-player1-mainprocess-player2-....)
# 6  
Old 06-07-2011
Quote:
Originally Posted by Shang
I have read about different approaches and decided to use SysV shared memory for a start.
Any particular reason? It's the same thing in the end, just a lot more convoluted.
Quote:
Assuming that we don't know how many clients(c) will connect and how many games(floor(c/2)) will be started the question is how to manage this shared memory segment?
My first idea was to create an array of pointers to game_state (type, see below), which would be the argument for shmat() function and store information about all games.
I don't understand what you mean by 'argument for shmat'. Do the games inherit shared memory for the parent or not? When you fork(), shared memory is inherited, so if the parent had it the children will start off with it and not need to fool with shmat().

Pointers won't work right in shared memory. Imagine that process A allocates memory and shoves the pointer into the shared mem. Process B tries to use this pointer, but process B has a different heap than process A. So B tries to use memory it never malloc()ed and crashes.

You have to store the contents in the shared memory, never heap pointers. Even pointers to the shared memory might not work unless every process maps the memory in the exact same place. You could store an array index, if the array was in shared mem too.
Quote:
But how to dynamically expand this array in case of new game start without ruining attachment?
What do you mean by 'ruining attachment'?

I know that when mmap() in a segment, pages won't actually be allocated until you use them. Just make a big enough memory segment in the first place and the OS will dynamically allocate more pages as you use them. I'm not sure sysv has this same ease and simplicity.
Quote:
How to implement reading and modification of shared memory segment in turns? (player1-mainprocess-player2-mainprocess-player1-mainprocess-player2-....)
How about, each player gets its own sem, so player 1 waits on sem 1, does its turn, posts on sem 2. Player 2 waits on sem 2, does its turn, and posts on sem 3. Player 3 waits on sem 3, does its turn, posts on sem 1.

That could be a ridiculous number of semaphores for a lot of clients, though. You could have an integer stored in shared memory of whose turn it is, and when a client is created they poll it until they're told it's their turn, then they sem_wait()/sem_post()/sem_wait()/sem_post()... I think the order would remain stable after that.

As for your game structure -- instead of a structure full of big arrays, how about a big array of structures?
# 7  
Old 06-07-2011
Quote:
Originally Posted by Corona688
Any particular reason? It's the same thing in the end, just a lot more convoluted.
I read on stackoverflow.com that it is more portable. I have no particular must, just curiosity, I am also reading about POSIX ones.
Quote:
Originally Posted by Corona688
Do the games inherit shared memory for the parent or not? When you fork(), shared memory is inherited, so if the parent had it the children will start off with it and not need to fool with shmat().
Oh, I haven't noticed that fact. Good to know.
Quote:
Originally Posted by Corona688
You have to store the contents in the shared memory, never heap pointers.
Ok, I will remember that.
Quote:
Originally Posted by Corona688
Even pointers to the shared memory might not work unless every process maps the memory in the exact same place.
Do you mean that below code is wrong?
Code:
int shm;
key_t key;
game_state *gsbuf;

if((key = ftok(".",'s')) < 0) ERR("ftok"); // still don't know why here is 's', copied from some webpage
shm = makeshm(sizeof(gsbuf), key);
if((gsbuf = shmat(shm, NULL, 0)) == (void *) -1) ERR("shmat");

/* then some forking */

(...)

/* outside main */
int makeshm(size_t size, key_t key) {
    int shm;
    if((shm = shmget(key,size,IPC_CREAT|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH))<0)
         ERR("Create shared memory");
    return shm;
}

Quote:
Originally Posted by Corona688
Just make a big enough memory segment in the first place and the OS will dynamically allocate more pages as you use them.
I think that is my problem. What does it mean big enough? Server doesn't know how much clients would have. The main point is how to organize this shared memory to grow as new games are started.
Quote:
Originally Posted by Corona688
That could be a ridiculous number of semaphores for a lot of clients, though. You could have an integer stored in shared memory of whose turn it is, and when a client is created they poll it until they're told it's their turn, then they sem_wait()/sem_post()/sem_wait()/sem_post()... I think the order would remain stable after that.
Good idea, thanks Smilie
Quote:
Originally Posted by Corona688
As for your game structure -- instead of a structure full of big arrays, how about a big array of structures?
I am not sure if I understand well. Could you propose any sketch?
Login or Register to Ask a Question

Previous Thread | Next Thread

8 More Discussions You Might Find Interesting

1. Linux

Unable to install VLC media player or any other player in SL 6.3 distro

Hi, I am unable to install VLC or any other media players in my SL 6.3 distro. I am using yum utility to install the packages, but i am getting the below error messages, --> Processing Dependency: libpng15.so.15()(64bit) for package: vlc-core-2.0.3-1.fc18.x86_64 --> Processing... (1 Reply)
Discussion started by: vel4ever
1 Replies

2. Programming

need help in forking

I have an input file with contents like: 5785690|68690|898809 7960789|89709|789789 7669900|87865|659708 7869098|65769|347658 so on.. I need to pass this file to 10 parallely running processes (forking)so that each line is processed by a process and no line is processed twice and write the... (1 Reply)
Discussion started by: rkrish
1 Replies

3. Programming

forking within a thread

Is it safe to call fork+exec in a multithreaded application. Because In my multithreaded application, I need to execute another program in each thread. I am using solaris 10. Any suggestions pls. (2 Replies)
Discussion started by: axes
2 Replies

4. HP-UX

Mozilla & Macromedia Flash Player Plugin Problem

Hello All, I am using Mozilla 1.7.8 on hp-ux 11.00, and install flash player 6 for it. it is giving following errors and get crashed. when i want to open a site need flash plugin. Gtk-WARNING **: invalid cast from `GtkSuperWin' to `GtkWidget' Gtk-WARNING **: invalid cast from `GtkSuperWin'... (1 Reply)
Discussion started by: Awadhesh
1 Replies

5. UNIX for Advanced & Expert Users

Forking

When I compile this C programme I get different outputs each time I run it Please explain to me whats happening in the code if you can give me a detailed explanation with the schedular functionality it will help a lot. Because I am stuck with this. #include <stdio.h> main(){... (3 Replies)
Discussion started by: manjuWicky
3 Replies

6. Programming

Forking in a loop

When I compile this C programme I get different outputs each time I run it Please explain to me whats happening in the code if you can give me a detailed explanation. Because I am stuck with this. #include <stdio.h> main(){ int i = 0; printf("I am the... (1 Reply)
Discussion started by: manjuWicky
1 Replies

7. Linux

Having player problem && need your help.

My System is FC3, The following Players don't run well: 1).Helix Player couldn't play MP3 and *.wma files, 2).Totem is the same, 3)XMMS couldn't play .wma files. I am a newer of Linux,but I like Linux,just as you. Could you help me? Thank you! (1 Reply)
Discussion started by: letcorpmuv
1 Replies

8. UNIX for Dummies Questions & Answers

Association b/w sockets & processes

Hi, Is there any way i can know the association between sockets and the processes which created them. :confused: (5 Replies)
Discussion started by: soorajmu
5 Replies
Login or Register to Ask a Question