2017-04-14 2 views
1

Cでクライアント/サーバーチャットルームを作成しました。接続されているすべてのクライアントのグローバルテーブルを作成する必要があります。私はこれを行う方法を理解することはできません。私はいくつかの並べ替えの構造体を作成し、すべての特定のソケットディスクリプタを追加する必要があると思う私は、各スレッドを生成します。それから、その構造内のすべての特定のSDに自分のメッセージを送る必要があります。グローバルなクライアントテーブルC:チャットルーム

私はこれをコード化する方法がわかりませんし、誰かが私にすべての接続が作成された後に書かなければならないもののいくつかのコード例を表示できるかどうかを見たいと思っていました。 。必要に応じて私のサーバーコードは以下の通りです。

#include <stdio.h> 
#include <stdlib.h> 
#include <pthread.h> 
#include <sys/socket.h> 
#include <unistd.h> 
#include <string.h> 
#include <malloc.h> 
#include <netinet/in.h> 
#include <sys/types.h> 
#include <errno.h> 
#include <netdb.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
void * 
client_session_thread(void * arg) 
{ 
    int  SD; 
    char request[2048]; 
    char message[2048] = "server receives input: "; 
    int  chatfile; 
    char msgr[50000]; 

    SD = *(int *)arg; 
    free (arg); 
    pthread_detach(pthread_self()); 

    chatfile = open("chathistory.txt", O_RDWR|O_CREAT|O_EXCL,0666); 
    close(chatfile); 

    chatfile = open("chathistory.txt", O_RDWR | O_APPEND); 
    read(chatfile,msgr,sizeof(msgr)); 
    write(SD, msgr, strlen(msgr)); 

    while (read(SD, request, sizeof(request))) 
    { 
     strcat(message, request); 
     strcat(message,"\n"); 
     fprintf(stdout, message); 
     write(SD,request,strlen(request)); 
     write(chatfile,request,strlen(request)); 
     strcpy(request,""); 
     strcpy(message, "server receives input: "); 
     bzero(request, sizeof(request)); 
     bzero(message,sizeof(message)); 
    } 
    close(SD); 
    close(chatfile); 
    return 0; 
} 

int main(int argc, char *argv[]) 
{ 

//create a socket. SD is my socket. 
    struct addrinfo  addrinfo; 
    struct addrinfo * result; 
    char message[256]; 
    int SD; 
    int FD; 
    pthread_t ignore; 
    int * FDpntr; 
    int on = 1; 

    addrinfo.ai_flags = 0; 
    addrinfo.ai_family = AF_INET;  // IPv4 only 
    addrinfo.ai_socktype = SOCK_STREAM; // Want TCP/IP 
    addrinfo.ai_protocol = 0;  // Any protocol 
    addrinfo.ai_addrlen = 0; 
    addrinfo.ai_addr = NULL; 
    addrinfo.ai_canonname = NULL; 
    addrinfo.ai_next = NULL; 

    if (getaddrinfo("clamshell.rutgers.edu", "5700", &addrinfo, &result) !=0) 
    { 
     printf("\x1b[1;31mProblem with getaddrinfo\x1b[0m\n"); 
    } 
//Create socket 
    SD = socket(AF_INET, SOCK_STREAM, 0); 
    if (SD == -1) 
    { 
     printf("\x1b[1;31mProblem creating socket\x1b[0m\n"); 
    } 
//Bind the socket to our specified IP and port 
    if (setsockopt(SD, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) ==-1) 
    { 
     printf("\x1b[1;31mProblem with sockopt\x1b[0m\n"); 
     freeaddrinfo(result); 
    return -1; 
    } 
    if (bind(SD, result->ai_addr, result->ai_addrlen) != 0) 
    { 
     printf("\x1b[1;31mProblem binding socket\x1b[0m\n"); 
    } 
    //first we bind our socket and then recast our address just like in client 
//Listen function listens for connections 
    if (listen(SD, 20) == -1) 
     { 
      printf("\x1b[1;31mProblem with listen\x1b[0m\n"); 
      close(SD); 
      return 0; 
     } 
    else 
     { 
//Accept function for accepting incoming connection 
     //sos = sizeof(struct sockaddr_in); 
     //while (FD = accept(SD, (struct sockaddr *)&client, (socklen_t*)&sos)) 
     while ((FD = accept(SD,0,0)) != -1) 
     { 
      FDpntr = (int *)malloc(sizeof(int)); 
      *FDpntr = FD; 
      if (pthread_create(&ignore, NULL, client_session_thread, FDpntr) != 0) 
      { 
       printf("\x1b[1;31mProblem creating thread\x1b[0m\n"); 
      } 
      else 
      { 
       continue; 
      } 
     } 
     close(SD); 
     return 0; 
    } 
} 
+0

構造体の代わりに配列を意味しますか?構造体はかなり剛性があります。配列は、1-nソケット記述子を保持できるという意味で拡張可能です。 – skylerl

+0

はいアレイが適切です。ごめんなさい。 –

答えて

0

は、別のファイルを実装することを推奨します。

initializeClientTable() 
destroyClientTable() 
addClient() 
deleteClient(), 
getClient() 

getClient()関数は、クライアントが返されます:ファイルはエントリポイントを持っているでしょう

はClientTableの終わりに、このようなイベントの表示を返す場合ClientTable

からget the first client又はget the next clientに示すパラメータ(おそらく列挙値)を有するであろう。

ClientTableは、リンクリストとして簡単に実装できます。