2012-01-23 4 views
0

私は単純なメモリゲーム用のサーバを作っています。クライアントのサーバレスポンスを管理する際のC分解処理のサーバ

私のプログラムでは分解に少し助けが必要ですが、私が望むのは分かっていますが、fork()を使って多くの経験をしていないので、C言語でどう書くべきかわかりません。私の目的は、私のサーバーの "SKELETON"の説明です。メッセージを送受信し、警告もエラーもなくコンパイルしました。最後に私の質問をします。 Memory game example
そして、私はゲームの「セッション」のようなものを管理して問題を解決しています:

は、これは可能性メモリーゲームがどのように機能するかの例です。
サーバーはCにあり、クライアントはJavaで、すべてLinux上で実行します。だからそれは背景情報です。
私は1台のサーバーとクライアントを持っています。
私の動機は:
です。1.サーバーは、いくつかのアドレスとポートで起動します。
2.クライアントはサーバーに接続できます。
3.サーバーゲームを管理します。
状況サーバー:
game1 -client1、CLIENT2
game2の-client3、client4
...
gameN-clientX、clientYプロパティ。 (注:Nは明らかにnと同じではありません)
ゲームの数は約10になります。
サーバより多くのクライアントがある場合、彼らは残念です。私は何とかサーバがいっぱいであることを彼らに伝えます。
各ゲームは64個のint値の配列で表されます。これはアイコンの数を表します boolの長さ64といくつかの変数の配列も可能ですが(詳細はちょっとです)
この配列と変数は各ゲームの状態を表しますサーバーとクライアントは文字列メッセージで通信し、それらをデコードしてゲームの状態を更新します。
ゲーム管理の意味:
最初はサーバーがないため、サーバーを実行しています(インスタンスが1つしか存在しない可能性があります)。
1.サーバーはクライアントの接続を待機し、サーバー上にゲームはありません。
2.私はクライアントを実行し、クライアントはサーバー(IP、ポート)に接続することを決定します。サーバはクライアントのサーバ状態に送ります - ゲームはありますか?はいの場合、どのゲーム=(ゲームで扱えるゲームの記述子)ですか? 3.クライアントは1から3のオプションを持っています:
-a)ゲームを作成する=サーバーはスタッキングのゲーム状態を生成し、クライアントに情報を送信します(サーバークライアント上のゲームがない場合は、このオプションのみです)。
-b)ゲームクライアントが「準備ゲーム」に接続できる場合、他のクライアントがゲームを作成して対戦相手を待つことができます。クライアントは情報のゲームの状態を取得し、彼のゲームの状態の記録サーバーを設定します。 c)既にゲームが進行中でしたが、何らかの理由で1つのクライアントが接続を失ったため、クライアントは進行中のゲームに接続し直したいと思っています - 条件が受け入れられると、サーバーはゲーム状態を送信します続けることができます
4. 2人のクライアントを持つゲームは始めることができます。
5.移動中にボタンをクリックできるクライアントは、そのアクションを説明するメッセージを取得します。
6.サーバーは、アクションが処理される方法を決定し、クライアントの両方にメッセージを送信します(OBSERVERなど)何がすべきか、クライアントはおそらくメッセージを確認するでしょうが、これはもう少し詳しくです
7。サーバーがクラッシュしたり、ゲームが終了する前に閉じられる場合、すべてのゲームが失われます。私はちょうどサーバーがダウンしているようなクライアントで何かメッセージを書いて終了します
8.ゲームが正しく終了したら - ゲームが終了するか、または1つのクライアントがメニュー終了ゲームを終了してゲームを終了することを決定した場合、サーバはクライアントにゲームの終了を知らせるために何かを行い、ゲームはゲームのリストを削除し、私のサーバーの

コード:

#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; 
} 

だから私の質問は:私は別のプロセスで各クライアントやゲームを提供するために持っていると分解との助けを必要としています。 各ゲームの変数(配列、変数)はどこに配置する必要がありますか? fork()によると。

+0

タンゴには2回かかります。接続要求ごとにプロセスをフォークするので、プレイヤーはすべて異なるスペースに住み、通信できなくなります。まあ、すべてのクライアントがデータベースへの接続を開始した場合でも可能です。しかし、そのデータベースは*ゲームの状態*を管理する必要があります。このための古典的な方法は、すべての接続(とそれらの間の関連)を同時に扱う* monolitic *サーバーを持つことです。また、一度に1バイトずつread()を行うと、パフォーマンス賞を獲得できません。バッファリングコードを追加する必要があります。 – wildplasser

+0

それは学校の仕事です、私はプレーヤーとゲームを提供する必要がありますそれは我々が持っている状態の一つです。 – user1097772

+0

私のquestioに追加したこのコードは、私たちが学校で行ったいくつかのコード、パラレルサーバーの作り方に基づいています。私はデータベースを使用しません。 クライアント用のjavaとサーバー用のCが必要です。したがって、コミュニケーション作業を行う最も簡単な方法は、アクションを説明するものを説明するメッセージを含む文字列を送信し、反応を説明し、単にこのメッセージをデコードする別のメッセージを返すことです。 私の最大の問題は、ゲームデータと何をするべきか、そしてフォークされた部分を含めるべきかということです。 – user1097772

答えて

0

ゲームを含むデータ構造をmain()の先頭に置くことができますが、フォークされたプロセスによる同時アクセスから、semaphoreなどを使用してそれらを保護する必要があります。

+0

私は、この構造をフォークに入れることを考えていました。それぞれのゲームの1つのプロセスです。わかりません。それがベストアイデアであれば、問題を解決することは移動中の変数によって解決できる可能性があります。 move何も起こらない - respは変化しない。 しかし、私は、2つのクライアントが1つのプロセスによって提供されていることを処理する必要があるかどうかわかりません - 私は正しいプロセスを得る方法を意味します。 例:game1はproces no.1にあり、クライアント1と2はgame1に接続されていますので、このプロセスによってサービスされます。 – user1097772

+0

これは全く別のアーキテクチャです。クライアントごとに1つのプロセスがある瞬間、これは一般的なフォークされたサーバーパターンです。ゲームごとに1つのプロセスを持つことは不可能ではありませんが、実装するのがより複雑になるでしょうし、私は利益を見ません。 –

+0

だから、ちょうどいいアイデアだった...だから、1つのプロセス= 1つのクライアントを選択した方が良い:クライアントがゲームに接続しているすべての時間をアクティブにするか、クライアントが何らかのアクションを行うたびに新しいプロセスを作成する。 – user1097772

関連する問題