2017-04-14 162 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

指示get the first clientget the next client或当在ClientTable结束时,返回该事件的指示的参数(可能一个枚举值)。

ClientTable很容易实现为链表。