0
votes

I'm making server for simple Memory Game.

I need little help with decomposition in my program, I know what I want but I don't know how should I write it in C, cause I don't have many experiences with using fork(). There is description of my purposes, "SKELETON" of my server - work sending and receiving messages, compiled without warnings or errors, IN THE END I'll ask my question.

This is example how could memory game works: Memory game example
And I'm solving problem with managing something like game "sessions".
Server is in C and client in Java, all will run it on linux. So it's to background info.
I'll have one server and n clients.
My motivation is:
1. Server starts on some address and port.
2. clients can connect to a server.
3. server will manage games.
Situation server:
game1 -client1, client2
game2 -client3, client4
...
gameN-clientX, clientY. (note: N is obviously not same as n)
Number of games will be about 10.
If there is more clients than a server - they have a shame .. I will somehow tell them that server is full.
each game is represented by an array of 64 int values - it represents numbers of icons may be also array of bool length 64 and some variables (but it's just detail)
this array and variables will represent a state of each game and server and client will be communicating by string messages, I decode them and update the game state.
What I mean by game managing:
At the beginning there is no server- so I run the server (only one instance can exist).
1.Server wait for connection of clients, there is no game on server.
2. I run client, client decide to connect the server (ip, port). Server send's to client state of server - is there games? if yes, what games = (descriptor of games to be able to handle with games)? 3. Client has 1 to 3 options:
-a)create game = server generate staring game state, send info to client (if there is no game on server client has obviously only this option).
-b)if there some games client can connect to "prepared game" = some other client created the game and wait for opponent; client get the info abou game state and set his game state acording server. c)there was already some game in progress, but one client from some reason lost the connection, so client want connect back to the game which is in progress - if some conditions will be accepted, server will sent him a game state so the can continue
4. Game which has 2 clients can begin.
5. Client which on the move can click on the button, so client get message which describe that action
6. server decide how the action will be procesed and send the the message to the BOTH of clients (something like OBSERVER) what should the do, clients probably confirm the message but this is again just detail
7. If the server crash or will be closed before end of the games, all games will be lost, I just do in clients something like if the server is down, they will write some message and end
8.If the game end properly - the game ends or one client decide to end game by chosing in menu end game, server do the stuff to acknowledge clients about end of game and the game will be deleted of list of games and there will be again position for new game.

Code of my server:

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/un.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h> // kvuli inet_ntop
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>

#define MYADDRESS "127.0.0.1"  // the port users will be connecting to
#define MYPORT 10000  // the port users will be connecting to
#define MYFRONTA 10 // length of queue
#define MYMSGLEN 80 //max len of message

int sendMessage(char* msg, int socket){
    int length = strlen(msg);
    int ret;

    ret = write(socket, msg, length);
    return ret;
}

int readLine(void *vptr, size_t maxlen, int sockd) {
    int n, rc;
    char    c, *buffer;

    buffer = vptr;

    for ( n = 1; n < maxlen; n++ ) {

        if ( (rc = read(sockd, &c, 1)) == 1 ) {
            *buffer++ = c;
            if ( c == '\n' )
                break;
        }
        else if ( rc == 0 ) {
            if ( n == 1 )
                return 0;
            else
                break;
        }

    }

    *buffer = 0;
    return n;
}

int main(int argc, char **argv)
{
    int server_sockfd, client_sockfd;
    socklen_t server_len, client_len;
    struct sockaddr_in server_address;
    struct sockaddr_in client_address;

    server_sockfd = socket( AF_INET, SOCK_STREAM, 0 );
    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr = inet_addr( MYADDRESS );
    server_address.sin_port = htons( MYPORT );

    server_len = sizeof( server_address );
    //If the server binding fails
        if( bind( server_sockfd, ( struct sockaddr *)&server_address, server_len ) != 0 )
        {
                perror("oops: server-tcp-single");
                exit( 1 );
        }

    listen( server_sockfd, MYFRONTA );

    signal( SIGCHLD, SIG_IGN );//Zombie process protection

    while( 1 )
    {
        printf( "server wait...\n" );

        client_len = sizeof( client_address );
        client_sockfd = accept( server_sockfd, ( struct sockaddr *)&client_address, &client_len );
        //Info
        char str[INET_ADDRSTRLEN];
        inet_ntop(AF_INET,&(client_address.sin_addr), str, INET_ADDRSTRLEN);
        printf( "Connected client from %s\n", str );

        if( fork() == 0 )
        {
            char retezec[MYMSGLEN];
            readLine(retezec, MYMSGLEN, client_sockfd);

            printf( "Klient sent : %s\n", retezec );
            printf( "Server sends : %s\n", retezec );
            sendMessage(retezec, client_sockfd);
                close( client_sockfd );

            exit (0 );
        }
        else
            close( client_sockfd );

    }
    return EXIT_SUCCESS;
}

So my question is: I have to serve each client or game in separate process and need help with decomposition. Where should I place variables (arrays, variables) for each games? According to the fork().

1
It takes two to tango: you fork a process for each connection request, so the players will all live in different spaces and can not communicate. Well: they could if every client started a connection to a database. But that database would also have to manage the game state. The classic way for this is to have a monolitic server, which handles all the connections (and associations between them) simultaneously. Also: read()ing one byte at a time won't win you the performance award, you'll need to add some buffering code. - wildplasser
It's school work, I have to serve the players and games parallel it's one of condition we got. - user1097772
This code I added to my questio is based on some code we did in school, how to make parallel server. I won't use database. I must have java for clients and C for server. So the easiest way to make the communication work is send some string with message which explain what explain an action and back another message which explain reaction and just "decode this message". My biggest problem is what to do with game data and what should include forked part ... - user1097772
The idea is that after the fork, parent and child are separated : they do not share data. They have (copies of) the same data, but they are not able to use it to communicate. So, if this is a game-server, and one of the clients makes a move or plays a card, there will be no way to inform the server (the parent) or the other player (a sibling). For a game server, you need to share state (or at least communicate state changes ) - wildplasser
No. There is no communication path between parent and child, or child and other-child. Every (child) process is basically an island. - wildplasser

1 Answers

0
votes

You can put the data structure(s) containing the games at the top of main(), but you would need to protect them from concurrent access by the forked processes by using something like a semaphore.