2015-05-02 1 views
1

Я написал приложение для связи между двумя клиентами (один запустит приложение server.c, а другой - client.c). В этот момент все идет хорошо, обе стороны (клиент и сервер) могут отправлять и получать сообщения (в обеих сторонах есть два процесса: один для прослушивания и печати сообщений, а другой для приема и отправки сообщений).Многопоточное приложение для клиент-серверного чата на языке c

Существует то, что я до сих пор:

client.c

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

#include "aes.h" 

#define BSIZE 320 

uint8_t key[] = "qwertyuioplkjhg"; 
uint8_t iv[] = "123456789098765"; 

void error(const char *msg) { 
    perror(msg); 
    exit(0); 
} 

int main(int argc, char *argv[]) { 
    int sockfd, portno, n, pid; 
    struct sockaddr_in serv_addr; 
    struct hostent *server; 

    char buffer[BSIZE]; 
    char paddedData[BSIZE]; 
    unsigned char crypted_data[BSIZE]; 

    if (argc < 3) { 
     fprintf(stderr,"usage %s <hostname> <port>\n", argv[0]); 
     exit(0); 
    } 

    portno = atoi(argv[2]); 
    sockfd = socket(AF_INET, SOCK_STREAM, 0); 

    if (sockfd < 0) { 
     error("ERROR opening socket"); 
    } 

    server = gethostbyname(argv[1]); 

    if (server == NULL) { 
     fprintf(stderr, "ERROR, no such host\n"); 
     exit(0); 
    } 

    bzero((char *) &serv_addr, sizeof(serv_addr)); 

    serv_addr.sin_family = AF_INET; 
    bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length); 
    serv_addr.sin_port = htons(portno); 

    if(connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) { 
     error("ERROR connecting"); 
    } 

    //while(1) { 
    switch(pid = fork()) { 
    case -1: 
     error("ERROR fork"); 
    case 0: 
     while(1) { 
      //printf("Please enter the message: "); 
      bzero(buffer, BSIZE); 
      //printf("Message: "); 
      fgets(buffer, BSIZE - 1, stdin); 

      strncpy(paddedData, buffer, BSIZE); 
      AES128_CBC_encrypt_buffer(crypted_data, (unsigned char*)paddedData, BSIZE, key, iv); 

      n = write(sockfd, crypted_data, BSIZE - 1); 

      if(n < 0) { 
       error("ERROR writing to socket"); 
      } 
     } 
    default: 
     while(1) { 
      //bzero(buffer,256); 

      n = read(sockfd, buffer, BSIZE - 1); 

      AES128_CBC_decrypt_buffer((unsigned char*)paddedData, (unsigned char*)buffer, BSIZE, key, iv); 

      if(n < 0) { 
       error("ERROR reading from socket"); 
      } 

      printf("<<server>>: %s", paddedData); 
     } 
    } 

    close(sockfd); 

    return 0; 
} 

и server.c

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

#include "aes.h" 
#define BSIZE 320 

uint8_t key[] = "qwertyuioplkjhg"; 
uint8_t iv[] = "123456789098765"; 

int numberOfConnections = 0; 

void communications_handler(int); 

void error(const char *msg) { 
    perror(msg); 
    exit(1); 
} 

int main(int argc, char *argv[]) { 
    int sockfd, newsockfd, portno, pid; 
    socklen_t clilen; 
    struct sockaddr_in serv_addr, cli_addr; 

    if(argc < 2) { 
     fprintf(stderr, "ERROR, no port provided\n"); 
     exit(1); 
    } 

    sockfd = socket(AF_INET, SOCK_STREAM, 0); 

    if(sockfd < 0) { 
     error("ERROR opening socket"); 
    } 

    bzero((char*)&serv_addr, sizeof(serv_addr)); 

    portno = atoi(argv[1]); 

    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_addr.s_addr = INADDR_ANY; 
    serv_addr.sin_port = htons(portno); 

    if(bind(sockfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0) { 
     error("ERROR on binding"); 
    } 

    listen(sockfd, 5); 
    clilen = sizeof(cli_addr); 

    while(1) { 
     /* [1] */ 
     newsockfd = accept(sockfd, (struct sockaddr*)&cli_addr, &clilen); 
     numberOfConnections++; 
     printf("\nThere are %d clients connected!\n\n", numberOfConnections); 

     if (newsockfd < 0) { 
      error("ERROR on accept"); 
     } 

     pid = fork(); 

     if (pid < 0) { 
      error("ERROR on fork"); 
     } 

     if (pid == 0) { 
      close(sockfd); 
      communications_handler(newsockfd); 
      exit(0); 
     } 

     else { 
      close(newsockfd); 
     } 
    } 

    close(sockfd); 

    return 0; 
} 

void communications_handler(int sock) { 
    int n, pid; 
    char buffer[BSIZE]; 
    char paddedData[BSIZE]; 
    unsigned char crypted_data[BSIZE]; 

    switch(pid = fork()) { 
    case -1: 
     error("ERROR on fork"); 
    case 0: 
     while(1) { 
      n = read(sock, buffer, BSIZE - 1); 

      AES128_CBC_decrypt_buffer((unsigned char*)paddedData, (unsigned char*)buffer, BSIZE, key, iv); 

      if(n < 0) { 
       error("ERROR reading from socket"); 
      } 

      printf("<<client>>: %s", paddedData); 
     } 
    default: 
     while(1) { 
      bzero(buffer, BSIZE); 
      //printf("Message: "); 
      fgets(buffer, BSIZE - 1, stdin); 

      strncpy(paddedData, buffer, BSIZE); 
      AES128_CBC_encrypt_buffer(crypted_data, (unsigned char*)paddedData, BSIZE, key, iv); 

      for(int i = 0; i < numberOfConnections; i++) { 
       n = write(sock, crypted_data, BSIZE - 1); 
      } 

      if(n < 0) { 
       error("ERROR writing to socket"); 
      } 
     } 
    } 
} 

Теперь я хочу расширить эту программу, позволяя серверу для принять несколько соединений (я действительно сделал это, на server.c, в [1]).

Но есть одна проблема: как я могу реализовать связь между двумя (или более) клиентами (сервер будет принимать новые соединения, считывать данные со всех подключенных клиентов и отправлять данные всем клиентам).

Можно ли это сделать с помощью процессов?

+0

вы проверили, какие-либо уроки, потому что довольно буквально * тысячи * учебники и примеры серверов, принимающие и обработки нескольких соединений, если вы просто искать немного. Многие из них являются чат-серверами и клиентами. –

ответ

0

Посмотрите на руководстве Beej, чтобы неблокируемое программирование сокетов: http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#select

+2

Ваш ответ состоит не более, чем ссылка и будет совершенно бесполезным, если связь будет нарушена. Обобщите важную информацию, чтобы ваша почта отвечала на вопрос, даже если ссылка отсутствует. Затем вы можете сохранить ссылку в своем ответе в качестве ссылки и получить дополнительную информацию. – Stibu

Смежные вопросы