2017-12-03 5 views
0

私は、一度に1つのクライアントが接続し、コマンドを実行してから閉じることができるサーバを持っています。サーバは "現在接続されている" IPアドレスの配列リストを保持し、誰がコマンドを受け入れるかを知っています。 問題は、同じクライアントであるかのように扱われる同様のIPアドレスで動作する2つのクライアントがあることです。サーバは、異なるIPを持つ2つのクライアントが同じであると考えます。1クライアント(Cソケットプログラミング)

例: クライアントAのIPアドレスは255.255.255.153です。私はそれを接続するために言う、すべて正常に動作します。 クライアントBのIPアドレスは255.255.255.156です。私はそれを接続するように指示し、サーバーはそれがすでに接続されていると言います。

私のstrcmpは間違っていますか?それは別のものですか?助けてください。

// Variable Declarations 

int SIZE = 10; // Max number of agents 
char *agents[SIZE], // List of current connections 
    *times[SIZE]; // List of connection times 
char buffer[MAXBUF]; 
int bytes_read = 0; 
int total_bytes_read = 0; 
int found = 0, // Bool flag 
    i; 
struct tm ts; 
struct timeval connected[SIZE], 
       current, 
       difference; 
     time_t TIME; 

// Initialize array to NULL 
for(i = 0; i < SIZE; i++) { 
    agents[i] = NULL; 
} 

// Infinite Loop 
while (true) { 
    struct sockaddr_in client; 
    int clientSocket; 
    socklen_t clientLength = sizeof(client); 
    memset(&client, 0, clientLength); 
    clientSocket = accept(sd, (struct sockaddr *)&client, &clientLength); 

    memset(buffer,0,MAXBUF); 
    bytes_read = read(clientSocket, buffer, MAXBUF); 
    if (bytes_read < 0) 
     break; 
    fprintf(stdout,"\nRead %d bytes: [%s]\r\n", bytes_read,buffer); 

    char *connectedIP = inet_ntoa(client.sin_addr); 

    // Option 1: 
    if ((strcmp(buffer, "#JOIN")) == 0) { // Join list of connected agents 
     found = 0; 

     // Get current time for log 
     TIME = time(NULL); 
     ts = *localtime(&TIME); 

     // Print message to log 
     char buf[80]; 
     strftime(buf, sizeof(buf), "%a %Y-%m-%d %H:%M:%S %Z", &ts); 
     fprintf(log, "%s: Received a \"#JOIN\" action from agent \"%s\"", buf, connectedIP); 
     fprintf(log, "\n\n"); 
     fflush(log); 

     printf("\n%s Joining", connectedIP); 
     fflush(stdout); 
     // Handle #JOIN request appropriately 
     for (i = 0; i < SIZE; i++) { 
      printf("\nAgent[%d] == %s", i, agents[i]); 

      if (agents[i] == NULL) { 

      } 
      else if (strcmp(agents[i], connectedIP) == 0){ // Agent found in list 
       found = 1; 

       printf("\n%s is equal to %s", agents[i], connectedIP); 
       fflush(stdout); 

       // Write to agent 
       char response[] = "#ALREADY MEMBER"; 
       write (clientSocket, response, strlen(response)); 

       // Get time for log 
       TIME = time(NULL); 
       ts = *localtime(&TIME); 

       // Write to log 
       char buf[80]; 
       strftime(buf, sizeof(buf), "%a %Y-%m-%d %H:%M:%S %Z", &ts); 
       fprintf(log, "%s: Responded to agent \"%s\" with \"#ALREADY MEMBER\"", buf, connectedIP); 
       fprintf(log, "\n\n"); 
       fflush(log); 
       i = SIZE; 
      } 
     } 
     if (found == 0) { // Save IP to list/queue 
      for(i = 0; i < SIZE; i++) { 
       if (agents[i] == NULL) { 

        // Save IP to array 
        agents[i] = connectedIP; 

        printf("\nagents[%d] = %s\n", i, connectedIP); 
        fflush(stdout); 

        // Save time to arrays 
        gettimeofday(&connected[i], NULL); 
        TIME = time(NULL); 
        times[i] = TIME; 
        ts = *localtime(&TIME); 

        // Write to log 
        char buf[80]; 
        strftime(buf, sizeof(buf), "%a %Y-%m-%d %H:%M:%S %Z", &ts); 
        fprintf(log, "%s: Responded to agent \"%s\" with \"#OK\"", buf, connectedIP); 
        fprintf(log, "\n\n"); 
        fflush(log); 

        // Write to agent 
        char response[] = "#OK"; 
        write (clientSocket, response, strlen(response)); 
        i = SIZE; 
       } 
      } 
     } 
     memset(&client, 0, clientLength); 
    } 
+1

あなたは 'agents'配列がどのように定義されているか、AFAICSを表示しません。それを適切に定義してIPv4アドレスを文字列として格納すると、 'strcmp()'はOKであるはずです。しかし、各アドレスを格納するために16バイトを許可する必要があります。 3単位の'192 ' '192 \ 0'のいずれかです。したがって、表示されていないコードには多くのヒンジがあります。 MCVE([MCVE])の作成方法をお読みください。あなたが示すものはMCVEではありません。 –

+0

「エージェント」宣言を追加しました。コメントは残念です。修正されました。 – Carr

+0

あなたは 'agents [i] = connectedIP;'を保存します。宣言されていない変数ですが、すべてのエージェントに同じスペースを使用している可能性があります。彼らはすべて同じだと思う。私は 'strdup(connectedIP)'のようなものを期待しています。しかしそれはまだMCVEではないので、人々があなたに手伝ってもらうのは便利ではありません。 –

答えて

1

inet_ntoa()ためPOSIX仕様情報を含む:

inet_ntoa()機能は、インターネット標準ドット表記の文字列の中で指定されたインターネットホストアドレスを変換しなければなりません。

inet_ntoa()関数はスレッドセーフである必要はありません。

inet_ntoa()のためのLinuxのmanページには、それが動作し、POSIXの警告は、そのプラットフォーム上で何を意味するのか方法の詳細については、明示的である:

inet_ntoa()機能は、ネットワークバイトオーダでのインターネットホストアドレスを変換し、 IPv4のドット付き10進表記の文字列に変換します。文字列は静的に割り当てられたバッファーに戻され、それ以降の呼び出しは上書きされます。

私は(はい、そのコメントの最初の部分は正確ではなかった - それはiPhoneアプリのハード読み取りコードです)commentに述べたように:

...しかし、あなたが使用している可能性がありますすべてのエージェントのためのスペースが同じであるため、接続されたエージェントを繰り返して名前を印刷すると、それらのエージェントはすべて同じであることがわかります。私はそこにstrdup(connectedIP)のような何かを期待しています。

これはあなたのコードは、単にagents配列にinet_ntoa()によって返されたポインタを保存しているため、配列は常に最後のホストを見上げ含まれていることを意味します。結果をinet_ntoa()からコピーして保存し、ストレージを管理する必要があります。最も簡単な方法は、strdup()でコピーを取ることですが、接続が切断されたときにそれを解放することを覚えておく必要があります。

strdup()またはそれと同等のメカニズムを使用すると、すぐに問題が解決するはずです。メモリリークを注意してください。

+0

私は 'strdup(inet_ntoa(client.sin_addr))'をやってしまいました。どうもありがとうございます。私は 'connectedIP'に結果を格納することは、ポインタだけでなく実際の文字列を保存すると考えました。再度、感謝します – Carr

関連する問題