2016-02-13 182 views
1

我們給了這段代碼,並且應該修改它,以便每當客戶端連接到服務器併發送消息時,服務器應該回復我聽到你的兄弟。這對於一個和多個客戶端是有效的,但接下來的任務是當新客戶端連接服務器時應該告訴所有其他連接的客戶端。C Sockets客戶端/服務器pthreads服務器廣播

我認爲這將是相當簡單的,但它不像我想的那樣工作。由於服務器總是得到sock 3,第一個客戶端得到4,第二個客戶端得到5等,我試圖做一個for循環,消息每當一個新的客戶端連接循環將發送消息到4,5只是使服務器直接關閉自己。然後,我嘗試着創建一個新客戶端連接時,服務器應該向第一個客戶端(4)發送消息,但只有當客戶端(4)向服務器寫入消息時,他纔會收到服務器發送的廣播消息。

因此,看起來客戶想要編寫,但需要寫一些東西,然後他才能從服務器接收廣播,任何幫助將不勝感激,因爲我們有點兒是初學者。

這就是代碼現在的樣子。

server.c

#include <stdio.h> 
#include <errno.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <sys/times.h> 
#include <arpa/inet.h> 
#include <netinet/in.h> 
#include <netdb.h> 
#include <string.h> 
#include <pthread.h> 

#define PORT 5555 
#define MAXMSG 512 


void *connection_handler(void *socket_desc) 
{ 
    int sock = *(int*)socket_desc; 
    int read_size; 
    char *message, client_message[2000], *message_to_client; 
    message = "Greetings! I am your connection handler\n"; 
    write(sock, message, strlen(message)); 
    while((read_size = recv(sock, client_message, 2000, 0)) > 0) 
    { 
     client_message[read_size] = '\0'; 
     printf("Client[%d]: %s", sock, client_message); 
     message_to_client = "I hear you dude..."; 
     write(sock, message_to_client, 19); 
     memset(client_message, 0, 2000); 
    } 

    if(read_size == 0) 
    { 
     printf("Client[%d] disconnected", sock); 
     fflush(stdout); 
    } 
    else if(read_size == -1) 
    { 
     perror("recv failed"); 

    } 
    free(socket_desc); 
    return 0; 
} 

int makeSocket(unsigned short int port) { 
    int sock; 
    struct sockaddr_in name; 
    /* Create a socket. */ 
    sock = socket(PF_INET, SOCK_STREAM, 0); 
    if(sock < 0) { 
     perror("Could not create a socket\n"); 
     exit(EXIT_FAILURE); 
    } 
    name.sin_family = AF_INET; 
    name.sin_port = htons(port); 
    name.sin_addr.s_addr = htonl(INADDR_ANY); 
    if(bind(sock, (struct sockaddr *)&name, sizeof(name)) < 0) { 
     perror("Could not bind a name to the socket\n"); 
     exit(EXIT_FAILURE); 
    } 
    return(sock); 
} 

int main(int argc, char *argv[]) 
{ 
    int sock; 
    int clientSocket; 
    int i; 
    int *new_sock; 
    char *broadcast; 
    fd_set activeFdSet, readFdSet; 
    struct sockaddr_in clientName; 
    socklen_t size; 
    sock = makeSocket(PORT); 
    if(listen(sock,1) < 0) 
    { 
     perror("Could not listen for connections\n"); 
     exit(EXIT_FAILURE); 
    } 
    FD_ZERO(&activeFdSet); 
    FD_SET(sock, &activeFdSet); 
    while(1) 
    { 
     printf("Waiting for connections\n"); 
     readFdSet = activeFdSet; 
     if(select(FD_SETSIZE, &readFdSet, NULL, NULL, NULL) < 0) 
     { 
      perror("Select failed\n"); 
      exit(EXIT_FAILURE); 
     } 
     for(i = 0; i < FD_SETSIZE; ++i) 
     { 
      if(FD_ISSET(i, &readFdSet)) 
      { 
       if(i == sock) 
       { 
        size = sizeof(struct sockaddr_in); 
        pthread_t sniffer_thread; 
        while((clientSocket = accept(sock, (struct sockaddr *)&clientName, (socklen_t *)&size))) 
        { 
         puts("Connection accepted"); 
         new_sock = malloc(1); 
         *new_sock = clientSocket; 
         if(pthread_create(&sniffer_thread, NULL, connection_handler, (void*) new_sock) < 0) 
         { 
          perror("could not create thread"); 
          return 1; 
         } 
         broadcast = "NEW CLIENT CONNECTED"; 
         write(4, broadcast, sizeof(broadcast)); //just to see if when ever a new client connects the first client should get all these messages 
         write(4, broadcast, sizeof(broadcast)); 
         write(4, broadcast, sizeof(broadcast)); 
         pthread_detach(sniffer_thread); 
         puts("Handler assigned"); 
         FD_SET(*new_sock, &activeFdSet); 

        } 
        if(clientSocket < 0) 
        { 
         perror("Could not accept connection\n"); 
         exit(EXIT_FAILURE); 
        }     
       } 
       else 
       { 
        if(readMessageFromClient(i) < 0) 
        { 
        close(i); 
         FD_CLR(i, &activeFdSet); 
        } 
       } 
      } 
     }  
    } 
} 

和客戶端的代碼看起來像這樣

client.c

#include <stdio.h> 
#include <errno.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <netdb.h> 

#define PORT 5555 
#define hostNameLength 50 
#define messageLength 256 

void initSocketAddress(struct sockaddr_in *name, char *hostName, unsigned short int port) 
{ 
    struct hostent *hostInfo; 
    name->sin_family = AF_INET; 
    name->sin_port = htons(port); 
    hostInfo = gethostbyname(hostName); 
    if(hostInfo == NULL) 
    { 
    fprintf(stderr, "initSocketAddress - Unknown host %s\n",hostName); 
    exit(EXIT_FAILURE); 
    } 
    name->sin_addr = *(struct in_addr *)hostInfo->h_addr; 
} 
void writeMessage(int fileDescriptor, char *message) 
{ 
    int nOfBytes; 
    nOfBytes = write(fileDescriptor, message, strlen(message) + 1); 
    if(nOfBytes < 0) 
    { 
    perror("writeMessage - Could not write data\n"); 
    exit(EXIT_FAILURE); 
    } 
} 

int main(int argc, char *argv[]) 
{ 
    int sock; 
    struct sockaddr_in serverName; 
    char hostName[hostNameLength]; 
    char messageString[messageLength]; 
    char buffer[1024]; 
    if(argv[1] == NULL) 
    { 
    perror("Usage: client [host name]\n"); 
    exit(EXIT_FAILURE); 
    } 
    else 
    { 
    strncpy(hostName, argv[1], hostNameLength); 
    hostName[hostNameLength - 1] = '\0'; 
    } 

    sock = socket(PF_INET, SOCK_STREAM, 0); 
    if(sock < 0) 
    { 
    perror("Could not create a socket\n"); 
    exit(EXIT_FAILURE); 
    } 

    initSocketAddress(&serverName, hostName, PORT); 
    if(connect(sock, (struct sockaddr *)&serverName, sizeof(serverName)) < 0) 
    { 
    perror("Could not connect to server\n"); 
    exit(EXIT_FAILURE); 
    } 
    printf("\nType something and press [RETURN] to send it to the server.\n"); 
    printf("Type 'quit' to nuke this program.\n"); 
    fflush(stdin); 
    recv(sock, buffer, 1024, 0); 
    printf(buffer); 
    while(1) 
    { 
    printf("\n>"); 
     fgets(messageString, messageLength, stdin); 
     messageString[messageLength - 1] = '\0'; 
     if(strncmp(messageString, "quit\n",messageLength) != 0) 
     writeMessage(sock, messageString); 
     if(recv(sock, buffer, 1024, 0) > 0) 
       printf(buffer); 


    } 
} 

回答

2

你需要做一些改動你的代碼得到它加工。您沒有收到任何東西的原因是您的客戶被卡在

fgets(messageString,messageLength,stdin);這是一個阻塞呼叫,所以只需在客戶端創建一個接收消息的線程,以便它可以連續收聽。對代碼進行以下更改,它應該可以幫助您實現結果。

添加下面行的代碼客戶端:

client.c

void * receiveMessage(void * socket) 
{ 
    int sockfd, ret; 
    char buffer[1024]; 
    sockfd = (int) socket; 
    int count = 1; 
    memset(buffer, 0, 1024); 
    for (;;) 
    { 
     if (recvfrom(sockfd, buffer, 1024, 0, NULL, NULL) > 0) 
     { 
      fputs(buffer, stdout); 
      printf("\n"); 
     } 
    } 
} 

在主功能下面線

//creating a new thread for receiving messages from the server 
    read = pthread_create(&rThread, NULL, receiveMessage, (void *) sock); 
    if (read < 0) 
    { 
     printf("ERROR: Return Code from pthread_create() is %d\n", read); 
     exit(1); 
    } 

和變化添加while循環至低於

while(1) 
    { 
     printf("\n>"); 

     fgets(messageString, messageLength, stdin); 

     messageString[messageLength - 1] = '\0'; 

     if(strncmp(messageString, "quit\n",messageLength) != 0) 
     { 
      writeMessage(sock, messageString); 
     } 
    } 

Server.c(在連接處理程序中添加廣播消息)

void *connection_handler(void *socket_desc) 
{ 
    int sock = *(int*)socket_desc; 
    int read_size; 
    char *message, client_message[2000], *message_to_client; 
    char broadcast[50] = "new client connected"; 
    int num; 

    num = sock; 
    num--; 
    while(num > 3) 
    { 
     write(num, broadcast, strlen(broadcast)); 
     sleep(1); 
     num--; 
    } 

    while((read_size = recv(sock, client_message, 2000, 0)) > 0) 
    { 
     client_message[read_size] = '\0'; 
     printf("Client[%d]: %s", sock, client_message); 
     message_to_client = "I hear you dude..."; 
     write(sock, message_to_client, strlen(message_to_client)); 
     memset(client_message, 0, 2000); 
    } 

    if(read_size == 0) 
    { 
     printf("Client[%d] disconnected", sock); 
     fflush(stdout); 
    } 
    else if(read_size == -1) 
    { 
     perror("recv failed"); 

    } 

    free(socket_desc); 
    return 0; 
} 
+0

是的,這幾乎是我們如何使它工作的,忘記了讓客戶端讀while循環。 – frallan123