многопоточный сервер успешно принимает все многопоточные клиенты, но только первый клиент успешно получает данные с сервера - PullRequest
0 голосов
/ 10 марта 2020

Я делаю многопоточный чат-клиент и сервер. Клиенты отправляют текст диалога на сервер, а сервер отправляет его клиенту-отправителю и другим клиентам, но когда сервер принимает более одного клиента, первый клиент получает и отправляет данные успешно, а остальные клиенты только отправляют данные успешно не получают данных. Сервер успешно получает данные от всех клиентов. Вот код:

КЛИЕНТ:

size_t size;
pthread_t sender;
pthread_t receiver;   
int socket_fd;
int socket_file_transfer= -1500;
 char * nick;

void sig_handler(int signal){
        printf("term signal has been caught\n");

        pthread_cancel(sender);
        pthread_cancel(receiver);   
        close(socket_fd);
        printf("o socket foi fechado\n");        

}

struct file_transfer {
        int host_fd; 
    int file_fd;
    char * filename;
    int started;    
};


void *thread_send(void * socket);
void *thread_receive(void * socket);


int main(int argc,char * argv[]){
    struct sigaction sig_a;
    memset(&sig_a,0,sizeof(sig_a));
    sig_a.sa_handler=&sig_handler;
    sigaction(SIGINT,&sig_a,NULL);
    int port, n;
    struct sockaddr_in server_addr;
    struct hostent * server;
    nick=malloc(strlen(argv[3]));
    memcpy(nick,argv[3],strlen(argv[3]));
    char buffer[255],buffer2[80];
    port=atoi(argv[2]);
    socket_fd=socket(AF_INET,SOCK_STREAM, 0);

    server=gethostbyname(argv[1]);
    bzero((char *) &server_addr, sizeof(server_addr));  
        server_addr.sin_family = AF_INET;

    bcopy((char *)server->h_addr,(char *)&server_addr.sin_addr.s_addr,server->h_length);    

    server_addr.sin_port=htons(port);

    connect(socket_fd,(struct sockaddr *) &server_addr,sizeof(server_addr));
    perror("connect:"); 
    size=strlen(argv[3]);
    //sending nick size
    write(socket_fd,&size,sizeof(size_t));
    //sending NICK string
    write(socket_fd,argv[3],size);  

    char * string=malloc(60);


    size=0;
   bzero(buffer,255);
             int* params;
                params = malloc(sizeof(int));

                *params=socket_fd;
                printf("starting thread with socket %d\n", socket_fd);
                pthread_create(&sender,NULL,&thread_send,(void*) params);

            pthread_create(&receiver,NULL,&thread_receive,(void*) params);

            pthread_join(receiver,NULL);
            pthread_join(sender,NULL);

}

void *thread_send(void * socket){
        char dialogue[270];
                    char buffer[255];
    while(1){


        printf("thread_send running\n");

        read(0,buffer,255);         

        sprintf(dialogue,"[%s] %s",nick,buffer);            


        size_t size=strlen(dialogue);
                    write(*((int *) socket),&size,sizeof(size_t));
            write(*((int *) socket),dialogue,size);
            bzero(buffer,255);

        bzero(buffer,255);
    }

}

void *thread_receive(void * socket){

        struct tm *date;
            time_t tim;
        size_t size=0;
        char buffer[255];
    while(1){
            read(*((int*) socket),&size,sizeof(size_t));

             perror("read size of dialogue from client socket:\n");

            read(*((int *) socket),buffer,size);
            perror("read dialogue from cliente socket");                
            tim=time(NULL);
            date=localtime(&tim);

                    printf("[%d/%d/%d-%d:%d:%d] %s\n",date->tm_mday,date->tm_mon+1,date->tm_year-100,date->tm_hour,date->tm_min,date->tm_sec,buffer);


        bzero(buffer,255);
    }

}

СЕРВЕР:

struct peer {
    char * nick;
    int socketfd;

};

void * thread_client(void * socket);
void del_user(int fd); 

 int npeer=0; 
 struct peer peers[20];


pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;

int main(int argc, char *argv[]){
        struct sigaction s;
    memset(&s,0,sizeof(s));
    s.sa_handler = SIG_IGN;
    sigaction(SIGPIPE, &s, NULL);
    int sockfd,newsockfd,port;
    socklen_t clilen;
    char buffer[255];
    struct sockaddr_in serv_addr,cli_addr;
    bzero((char *) &serv_addr, sizeof(serv_addr));      
    int n;
    sockfd=socket(AF_INET,SOCK_STREAM,0);
    int reuse_addr = 1; 
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(int));

    port=atoi(argv[1]);
    serv_addr.sin_family=AF_INET;
    serv_addr.sin_addr.s_addr=INADDR_ANY;
    serv_addr.sin_port=htons(port);

    bind(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr));
    listen(sockfd,5);
    int fide[2];
    char * token[4];
    //fd_set wfds, tfds,rfds,afds,receiverfds;
                int* params;
    size_t size=0;
    //int status;
    //int newtransferfd=-1;
    char mem[255];
    clilen=sizeof(cli_addr);
    printf("starting accept():\n"); 
    while((newsockfd=accept(sockfd,(struct sockaddr *) &cli_addr,&clilen)) > 0){

                //RECEBER O TAMANHO DA STRING 
                read(newsockfd,&size,sizeof(size_t));
                //RECEBER A STRING
                read(newsockfd,buffer,size);


                //peers[npeer]=(struct peer *)malloc(sizeof(struct peer));
                peers[npeer].nick=malloc(strlen(buffer));
                strcpy(peers[npeer].nick,buffer);
                printf("nick size: %ld\n",strlen(peers[npeer].nick));
                peers[npeer].socketfd=newsockfd;
                char ip[30];
                getnameinfo((struct sockaddr *)&cli_addr,clilen,ip,30,NULL,0,NI_NUMERICHOST);
                printf("new client accepted: %s with fd=%d, ip=%s\n",peers[npeer].nick,peers[npeer].socketfd,ip);
                npeer=npeer+1;
                bzero(buffer,255);

                pthread_t *client=malloc(sizeof(pthread_t));

                params = malloc(sizeof(int));
                *params=newsockfd;
                printf("starting a thread with socket fd=%d\n", newsockfd);
                pthread_create(client,NULL,&thread_client,(void*) params);
                pthread_detach(*client);



            }
}       


void * thread_client(void * socket){
    int sockfd=*((int*) socket);
    free(socket);
    printf("starting thread with socket fd %d\n",sockfd);
    size_t size;
    int status=1;
    char buffer[255];    
 while(status ){  

    size=0;
    if(read(sockfd,&size,sizeof(size_t)) == 0) {
           close(sockfd);
        del_user(sockfd);
        pthread_exit(NULL);
    }

    printf("size: %ld\n",size);    
    read(sockfd,buffer,size);    
    printf("%s\n",buffer);    
    if(strstr(buffer,"/exit") != NULL) {
            status=0;

     } else {
              pthread_mutex_lock(&mutex);

             for(int i=0;i<npeer;i++){
                    size=strlen(buffer);            

                    //perror("erro");                    
                    printf("socketfd from peers[%d]:%d\n",i,peers[i].socketfd);
                    write(peers[i].socketfd,&size,sizeof(size_t)); 
                        perror("first write");           
                    write(peers[i].socketfd,buffer,strlen(buffer));
                          perror("second write"); 
                                 bzero(buffer,255);
             }    
             pthread_mutex_unlock(&mutex);
    }                

 }
    close(sockfd);
    del_user(sockfd);
    pthread_exit(NULL);
}

void del_user(int fd){
    printf("del_user(int fd) is being run\n");
    int index=-1;
    for(int i=0;i<npeer;i++){
        if(peers[i].socketfd == fd)
            index=i;    
    }
    if(index!=-1){
        for(int i=index;i<npeer;i++){
            peers[i]=peers[i+1];

        }
        npeer=npeer-1;
        printf("npeer=%d\n",npeer);
    }
}

ВЫХОД:

СЕРВЕР:

$ ./server 12345
starting accept():
nick size: 7
new client accepted: client1 with fd=4, ip=127.0.0.1
starting a thread with socket fd=4
starting thread with socket fd 4
nick size: 7
new client accepted: client2 with fd=5, ip=127.0.0.1
starting a thread with socket fd=5
starting thread with socket fd 5
size: 16
[client1] hello

socketfd from peers[0]:4
first write: Success
second write: Success
socketfd from peers[1]:5
first write: Success
second write: Success
size: 16
[client2] hello

socketfd from peers[0]:4
first write: Success
second write: Success
socketfd from peers[1]:5
first write: Success
second write: Success

ПЕРВЫЙ КЛИЕНТ:

$ ./client localhost 12345 client1
connect:: Success
starting thread with socket 3
thread_send running
hello
thread_send running
read size of dialogue from client socket:
: Success
read dialogue from cliente socket: Success
[10/3/20-16:57:39] [client1] hello

read size of dialogue from client socket:
: Success
read dialogue from client socket: Success
[10/3/20-16:57:48] [client2] hello

ВТОРОЙ КЛИЕНТ:

$ ./client localhost 12345 client2
connect:: Success
starting thread with socket 3
thread_send running
read size of dialogue from client socket:
: Success
read dialogue from cliente socket: Success
[10/3/20-16:57:39] 
hello
thread_send running
read size of dialogue from client socket:
: Success
read dialogue from client socket: Success
[10/3/20-16:57:48] 

1 Ответ

0 голосов
/ 10 марта 2020

Это l oop:

    for(int i=0;i<npeer;i++){
            size=strlen(buffer);            
            //perror("erro");                    
            printf("socketfd from peers[%d]:%d\n",i,peers[i].socketfd);
            write(peers[i].socketfd,&size,sizeof(size_t)); 
            perror("first write");           
            write(peers[i].socketfd,buffer,strlen(buffer));
            perror("second write"); 
            bzero(buffer,255);
     }

Должен ли этот bzero (буфер, 255) быть там? Это выглядит неправильно, так как на следующей итерации вы берете его strlen () (спойлер - это ноль); затем записывает двоичное значение 0, а вторая запись ничего не записывает, потому что strlen (buffer) равен нулю. Кстати, у вас уже был strlen (буфер) в размере ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...