多线程客户端中由于文件描述符导致的分段错误

时间:2017-10-06 19:35:29

标签: c multithreading

我创建了一个具有多线程的客户端 - 服务器文件共享系统。客户端代码适用于单个客户端。当我增加客户端中的线程数时,服务器代码中会出现分段错误。

当我在gdb上执行代码时,它显示发生了错误分段错误,没有这样的文件或目录。这是因为线程共享文件描述符吗?如何解决分段错误?

---------- -----------编辑 我考虑了你的所有建议。大多数错误都已解决,但是当我尝试发送> 10mb文件时,某些send-recv调用在使用线程发送时不会完全执行(它可以在单个线程中正常工作)。我相信这就是内存泄漏发生的原因,并最终导致分段错误(文件指针未关闭)。 gdb也是如此。 如何解决此发送接收阻止错误?

客户端代码

#include <time.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<string.h>
#include<stdio.h>
#include <stdlib.h>
#include<pthread.h>
#include <semaphore.h>
#define PORT 8029
#define SIZE 1024
#define SERVER_ADDR "192.168.43.158"  //"10.15.36.112"
//defining number of threads



struct ser_data
{
  int sockfd;
  int n;
};

void *client_req(void * data){
//  printf("inside thread\n");

  //sleep(1);

  int s,c,n,read_size,r;
  //login_id and password of the user
  //array to choose file names randomly
  //char f_name[20][20]={"f0.txt","f1.txt","f2.txt","f3.txt","f4.txt","f5.txt","f6.txt","f7.txt","f8.txt","f9.txt","f10.txt\0","f11.txt\0","f12.txt\0" ,"f13.txt\0","f14.txt\0","f15.txt\0","f16.txt\0","f17.txt\0","f18.txt","f19.txt"};
  //socket address for client and server
  //used for generation of random no
  time_t t;
  struct sockaddr_in cli,serv;

  FILE *f;
  char fname[SIZE]="file_cli/";
  char f_name[SIZE];
  char login_id[21], pswd[21], choice[2];
  //msg_cli_rec= message recieved form server
  char msg_cli_rec[SIZE];
  //msg_cli_send =message sent by client
  char  msg_cli_send[SIZE];

  time_t start, stop;
  int brk=0;

  start = time(NULL);

  s=socket(AF_INET,SOCK_STREAM,0);
  bzero((char*)&serv,sizeof(cli));
  cli.sin_family=AF_INET;
  cli.sin_port=htons(PORT);
  cli.sin_addr.s_addr = inet_addr(SERVER_ADDR);
  connect(s,(struct sockaddr*)&cli,sizeof(cli));

  //printf("\nConnected with server");

  strcpy(choice, "1");

  /*msg_cli_rec = (char *) malloc(1000* sizeof(char));
  msg_cli_send = (char *) malloc(1000* sizeof(char));*/

//if user wants to login
  if(strcmp(choice,"1")==0)
   {

     strcpy(login_id, "prach");
     send(s, login_id, sizeof(login_id), 0);

     strcpy(pswd, "prach");
     send(s, pswd, sizeof(pswd), 0);
   }


  //making default choice download 1


  do {

      strcpy(choice, "1\0");
      strcpy(msg_cli_send, choice);
      //send(s, choice, sizeof(choice), 0);
      send(s,msg_cli_send,sizeof(msg_cli_send),0);

      //random number generation
      srand((unsigned) time(NULL));
      //r=((unsigned)rand()*(i++))%20;

      r=15;
      if(strcmp(choice,"1")==0)
      {
        /*if(recv(s, msg_cli_rec, sizeof(msg_cli_rec), 0))
        {
          //if((strcmp("end",msg_cli_rec))==0)break;
          printf("\n%s", msg_cli_rec);
        }*/
        /*printf("\nEnter the file name you want:");
        scanf("%s", msg_cli_send);*/

        // to select file name with index of the random number
        sprintf(f_name,"file (%d).txt",r);
        strcpy(msg_cli_send, "");

        strcpy(msg_cli_send,f_name);

    //    printf("\n%s",msg_cli_send);
      //  printf("\n rand =%d\n", r );
        send(s,msg_cli_send,sizeof(msg_cli_send),0);

      //  printf("\nThe received file content is:");
        //receiving the file names

        f = fopen(strcat(fname,f_name),"w");

        bzero( msg_cli_rec, sizeof(msg_cli_rec));
        while((recv(s, msg_cli_rec, sizeof(msg_cli_rec), 0)> 0)&&(*msg_cli_rec!='\0'))
        {//fflush(stdout);
          if((strcmp("quit",msg_cli_rec))==0)break;
          fprintf(f, "%s", msg_cli_rec);
          //printf("\n%s", msg_cli_rec);
          bzero( msg_cli_rec, sizeof(msg_cli_rec));
        }
      //  printf("File recieved");
        fclose(f);
        strcpy(fname,"\0" );
        //sem_post(&sem);
      }

   stop = time(NULL);
  // printf("\n%s\n", ctime(&stop));

  //printf("%ld", (stop-start));


  //set the timer to 300 seconds
}while(*choice == '1' && (stop-start)<10);

//tell the server that we are done with sending files
  strcpy(choice, "0");
  send(s, choice, sizeof(choice), 0);

  printf("%ld\n", (stop-start) );

/*  free(msg_cli_rec);
  free(msg_cli_send);*/

  close(s);
  //pthread_exit(NULL);
}


int main()
{
  int N_Threads=2, count =0;
  struct ser_data data;

  /*while(N_Threads<=2)
   {
     pthread_t t;
     pthread_create( &t , NULL ,  client_req , NULL);
     N_Threads++;
     if ( ! pthread_detach(t) )
       printf("Thread detached successfully !!!\n");
       //pthread_join(t, NULL);

   }*/


   while(count != N_Threads){
        pthread_t handle;
        count = count+1;
        data.sockfd = count;
                if(pthread_create(&handle, NULL, client_req,(void *)&data)<0)
                        error("Error creating thread");
                else
                        printf("Thread allocation successful for fd: %d\n",data.sockfd);

    }
    pthread_exit(NULL);

}

服务器代码

#include <time.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<string.h>
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<dirent.h>
#include <mysql/mysql.h>
#include <semaphore.h>
#define PORT 8029
#define SIZE 1024
#define QUERY_SIZE 200
#define N_Threads 5
#define SERV_ADDR "192.168.43.158"

clock_t start, stop;


//login id and password of the user

int file_id=1;
/*Database variables*/
MYSQL *db_conn;


char *db_server = "localhost";
char *db_user = "root";
char *db_password = "root";
char *database = "file_db";




//for synchronization while accessing the db
sem_t sem;


/* A function which generates the and returns login query statement*/
char* query_login(char *query, char *login_id, char *pswd)
{
    //generating query
    strcpy(query,"SELECT * FROM user_info WHERE user_id='");

    strcat(query, login_id);
    strcat(query, "' AND pswd='");
    strcat(query, pswd);
    strcat(query, "'");

    return query;
}

/* A function which generates and returns the register query statement*/
char* query_register(char *query, char *login_id, char *pswd)
{
    strcpy(query, "INSERT INTO user_info VALUES ( '");

    strcat(query, login_id);
    strcat(query, "', '");
    strcat(query, pswd);
    strcat(query, "' )");

    return query;
}


void *connect_client(void *socket)

{   int sock=*(int*)socket;
    printf("\nFD %d",sock);
    char msg_c_r[SIZE], msg_s_s[SIZE];
    //for the choice given to the user to login or register
    char choice='0';
    char msg_serv_send[SIZE],msg_serv_rec[SIZE];
    char msg_cli_rec[SIZE];
    char fpath[SIZE] = "file_serv/";
    char fname[SIZE];
    int read_size;
    int num_fields=0;
    char * line = NULL;
    size_t len = 0;
    ssize_t read;
    MYSQL_ROW row;
    MYSQL_RES *db_res;

    char login_id[21], pswd[21];

    FILE *f;
    FILE *fc;

    char name[SIZE];
    char query1[SIZE];
    char query[QUERY_SIZE];

    /*locking the database for mutual exclusion*/
    //sem_wait(&sem);

    //executing a query

    choice = '1';
    strcpy(query, "\0");

    switch(choice)
    {
    //1 = login
    case '1':

        /*to find the login id and password of the user*/

        bzero(login_id,  sizeof(login_id));

        recv(sock, login_id, sizeof(login_id), 0);

        bzero(pswd, sizeof(pswd));

        recv(sock, pswd, sizeof(pswd), 0);

        printf("The login id is: %s\nThe Password is: %s\n", login_id, pswd);

        //lock for accessing db in mutual exclusion
        sem_wait(&sem);
        query_login(query, login_id, pswd);

        //checking the details given by client

        if (mysql_query(db_conn, query)!=0) {
                fprintf(stderr, "%s\n", mysql_error(db_conn));
        }
        strcpy(query, "\0");
        strcat(query,"select * from user_info where user_id='");
        strcat(query,login_id);
        strcat(query,"'");
        mysql_query(db_conn, query);
        db_res = mysql_store_result(db_conn);
        row = mysql_fetch_row(db_res);
        if (row!=0) {
                //send(sock,"T",sizeof("T"),0);
                        printf("\nT");
        }

        //freeing the result variable so it can be used further
        mysql_free_result(db_res);
        //release lock
        sem_post(&sem);
        break;
    }//switch case
    /*send(sock, "\nPlease enter your choice \n 1- File Download \n 2-File Upload\n 3-Rating\n", sizeof("\nPlease enter your choice \n 1- File Download \n 2-File Upload\n 3-Rating\n"), 0);*/

    int nu=1;
    do{
            bzero(msg_serv_rec,sizeof(msg_serv_rec));
            if(recv(sock, msg_serv_rec,sizeof(msg_serv_rec), 0)>0)
            {
                choice = msg_serv_rec ? *msg_serv_rec : '0';
                printf("\n choice = %c\n", choice);
                strcpy(query, "\0");

            //printf("Client's choice is file Download\n" );
            /*Sending File to the client line by line
            checking the database connection*/
                if(choice == '1'){
            /*if(mysql_query(db_conn, "SELECT name FROM file_info")==0)
            {
                db_res = mysql_store_result(db_conn);
                num_fields = mysql_num_fields(db_res);
                if(num_fields>0)
                {
                    while ((row = mysql_fetch_row(db_res)))
                    {
                        for(int i = 0; i < num_fields; i++)
                        {
                            char *fname1=row[i] ? row[i] : "NULL";
                            strcat(name,fname1);
                            strcat(name, "\n");
                            //send(sock,name,sizeof(name),0);
                            //printf("\n%s",name);
                        }
                    }

                    //sending list of all files to client
                    send(sock,name,sizeof(name),0);*/
                    /*emptying the name!!
                    strcpy(name, "");*/

                    //freeing the result variable so it can be used further
                    /*mysql_free_result(db_res);
                    sem_post(&sem);*/
                    bzero(msg_serv_rec,sizeof(msg_serv_rec));

                    if(recv(sock, msg_serv_rec,sizeof(msg_serv_rec), 0)>0)
                    {//which file recieved

                    printf("%s\n", msg_serv_rec );
                //  sem_wait(&sem);

                    f = fopen(strcat(fpath, msg_serv_rec),"r");

                    while(fgets(msg_serv_send, sizeof(msg_serv_send), f) !=NULL)
                    {
                        if((*msg_serv_send!=EOF || *msg_serv_send!='\n'))
                        {

                            send(sock, msg_serv_send, sizeof(msg_serv_send), 0);
                            //printf("\n%s", msg_serv_send);
                        }
                        else
                        break;
                    }
                    send(sock,"quit",sizeof("quit"),0);
                    fclose(f);
                    strcpy(fpath, "file_serv/");
                    //sem_post(&sem);
                    printf("\nFile sent to the client\n");
                }

                }

                else if (choice == '0')
                    break;
                strcpy(msg_serv_rec, "");
                //stop = clock();
                //time(NULL);
            }

            else
            {
                choice = '0';
            }
            }while ( choice != 'f' && choice != '0');

    nu++;




    /* unblocking the semaphores to allow other threads to access*/
    //sem_post(&sem);


    if(read_size == 0)
    {
    puts("\nClient disconnected\n");
    fflush(stdout);
    }
    /*else if(read_size == -1)
    {perror("recv failed");}
    fclose(f);*/

    close(sock);

    pthread_exit(NULL);
}

int main()
{   int s,n,i, clilen;
    int c;
    int newsockfd;
    int *new_sock;

    start = clock();

    //pthread_t handle;
    struct sockaddr_in cli,serv;//socket address for client and server
    MYSQL_ROW row;
    MYSQL_RES *db_res;
    //initializing the semaphore
     sem_init(&sem, 0, 1);

    //synchronization in DB
    sem_wait(&sem);

    /*Database connectivity*/
    db_conn = mysql_init(NULL);
        /* Connect to database */
        if (!mysql_real_connect(db_conn, db_server, db_user, db_password, database, 0, NULL, 0)) {
            fprintf(stderr, "%s\n", mysql_error(db_conn));
            exit(1);
        }

        /* send SQL query */
        if (mysql_query(db_conn, "show tables")) {
            fprintf(stderr, "%s\n", mysql_error(db_conn));
            exit(1);
        }
        db_res = mysql_use_result(db_conn);

        /* output table name */
        printf("MySQL Tables in mysql database:\n");
        while ((row = mysql_fetch_row(db_res)) != NULL)
            printf("%s \n", row[0]);

    //freeing the result variable so it can be used further
    mysql_free_result(db_res);

    sem_post(&sem);


    //Server socket
    s=socket(AF_INET,SOCK_STREAM,0);
    bzero((char*)&serv,sizeof(serv));
    serv.sin_family=AF_INET;
    serv.sin_port=htons(PORT);
    serv.sin_addr.s_addr=inet_addr( SERV_ADDR);//"10.15.36.112");



    /*printf("\nServer is waiting for client to respond");
    i=0*/
    //accept the incomming connections from client


        bind(s,(struct sockaddr *)&serv,sizeof(serv));
        printf("\nAddress bind successful");

        listen(s,3000);//4 is the limit of the number of outstanding connections

        n=sizeof(cli);
/*
        i=0;
        //accept the incomming connections from client
        while( (c = accept(s, (struct sockaddr *)&cli, (socklen_t*)&n))) //&& (stop-start)<300 )
            {   puts("Connection accepted\n");
                        pthread_t t;

                        printf("sock =%d\n", c);
                if( pthread_create( &t , NULL ,  connect_client , (void*) c) < 0)
                {
                    perror("could not create thread");
                    return 1;
                }
                        i++;

                        /*Now detach the thread ,When a detached thread terminates, its resources are
           automatically released back to the system without the need for
           another thread to join with the terminated thread.*/
            /*   if ( ! pthread_detach(t) )
                     printf("Thread detached successfully !!!\n");

                puts("Handler assigned");
                stop = clock();
        }*/

        clilen=sizeof(cli);
     while(newsockfd = accept(s, (struct sockaddr *) &cli, &clilen))
     {
          if(newsockfd < 0)
               error("ERROR on accept");
          else{
               pthread_t handle;
               new_sock = malloc(1);
               *new_sock = newsockfd;
               if(pthread_create(&handle, NULL,connect_client ,(void *)new_sock)<0)
                    error("Error creating thread");
               else
                    printf("Thread fd: %d\n",newsockfd);
                             if ( ! pthread_detach(handle) )
                                     printf("Thread detached successfully !!!\n");
          }
     }


    /* close database connection */
  mysql_free_result(db_res);
  mysql_close(db_conn);

    close(s);

    /*destroying the mutex */
     sem_destroy(&sem);

    return 0;
}

0 个答案:

没有答案