0

我在 Linux 环境中编写多线程 ftp 协议时遇到分段错误问题。这种分割是由于 fclose() 文件功能。

这是我的代码

客户端代码:它测试客户端作为命令编写的任何内容。例如,如果他写“put filename”,它会通过打开这个文件将这个文件发送到服务器,将它逐个流读取到缓冲区中。这些流通过套接字发送到服务器端。

#include <stdio.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h> /* struct sockaddr_in, htons() */
#include <arpa/inet.h> /* inet_aton() */
#include <stdlib.h>

#define BUF_LENGTH 100

/*void getcmdstring(char ** args, char *cmd)
{
  int i=0;
  char * pch;
  pch = strtok (cmd," ");
  while (pch != NULL)
  {
  //args[i]=pch;
    stpcpy(args[i],pch);
    printf("%s,",args[i]);
    //printf("%s,",pch);
    pch = strtok (NULL, " ");
    i++;
  }
  //args[i]=NULL;

  //return argsVar;
}*/

int main(int argc, char ** argv)
{
    int port;
    int sock = -1;
    struct sockaddr_in address;
    //struct hostent * host;
    int len;
    //char ** args;
    /* checking commandline parameter */
    if (argc != 3)
    {
        printf("usage: %s hostIP port \n", argv[0]);
        return -1;
    }



    /* obtain port number */
    if (sscanf(argv[2], "%d", &port) <= 0)
    {
        fprintf(stderr, "%s: error: wrong parameter: port\n", argv[0]);
        return -2;
    }

//  port = atoi(argv[2]);       
    /* create socket */
    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock <= 0)
    {
        fprintf(stderr, "%s: error: cannot create socket\n", argv[0]);
        return -3;
    }

    /* connect to server */
    bzero(&address, sizeof(address));
    address.sin_family = AF_INET;
    address.sin_port = htons(port);
    if(inet_aton(argv[1], &address.sin_addr) <=0){
        fprintf(stderr,"inet_aton error for %s\n", argv[1]);
        return -4;
    }
    /*host = gethostbyname(argv[1]);
    if (!host)
    {
        fprintf(stderr, "%s: error: unknown host %s\n", argv[0], argv[1]);
        return -4;
    }
    memcpy(&address.sin_addr, host->h_addr_list[0], host->h_length);*/
    if (connect(sock, (struct sockaddr *)&address, sizeof(address))<0)
    {
        fprintf(stderr, "%s: error: cannot connect to host %s\n", argv[0], argv[1]);
        return -5;
    }

    char cmd[4096], cmd2[4096];
    char *fileS_path; 
    char cwd[2048];
    char buf_S[BUF_LENGTH];
    int varS;

    char *fileR_path;
    char cwd2[2048];
    char buf_R[BUF_LENGTH];
    int varR, varR2;

    char ** res  = NULL;

    char *  p    = strtok (cmd2, " ");
    int n_spaces = 0, i;

    FILE *fileS;

    while(1){

        printf("ftp>");

        fgets(cmd,4096,stdin);


        strcpy(cmd2, cmd);
        //printf("Cmd just after fgets: %s\n", cmd);

        p    = strtok (cmd2, " ");
        n_spaces = 0;

        if(cmd==NULL || strcmp(cmd, "")==0)
        printf("Something wrong with reading the command from the screen\n");
        else
        {
            /* split string and append tokens to 'res' */
            while (p) {
              res = realloc (res, sizeof (char*) * ++n_spaces);

              if (res == NULL)
                exit (-1); /* memory allocation failed */

              res[n_spaces-1] = p;

              p = strtok (NULL, " \n");
            }

            /* realloc one extra element for the last NULL */
            res = realloc (res, sizeof (char*) * (n_spaces+1));
            res[n_spaces] = 0;

            /* print the result */
            for (i = 0; i < (n_spaces+1); ++i)
              printf ("res[%d] = %s\n", i, res[i]);


            //printf("bar");    
            //printf("%s test before sending to socket\n", cmd);
            //if(write(sock, cmd, 4096)<0)
            //printf("problem with sending the socket  command \n");
            //else 
            //{

                if(strcmp(res[0], "quit\n")==0)
                break;
                else if(res[0]!=NULL && res[1] !=NULL && strcmp(res[0], "put")==0)
                {
                    if(write(sock, cmd, 4096)<0)
                    printf("problem with sending the socket command \n");
                    else{
                        // Sending file from the client to the server 
                        printf("\n");
                        printf("****SENDING****\n");

                        if(getcwd(cwd,sizeof(cwd))!=NULL)
                        {
                            fileS_path=cwd;
                            strcat(fileS_path, "/");
                            strcat(fileS_path, res[1]);
                        }


                        printf("Sending the file %s to the server...\n", fileS_path);


                        printf("%s\n", fileS_path);
                        fileS = fopen(fileS_path, "r");
                        printf("OK apres creation file\n");
                        if(fileS==NULL)
                        fprintf(stderr, "File %s is not found. \n", fileS_path);
                        else
                        {
                            printf("else after creation file\n");
                            bzero(buf_S,BUF_LENGTH);
                            printf("bzero buffer1\n");
                            varS=-1;
                            printf("after initializing varS %d \n", varS);
                            while((varS=fread(buf_S, sizeof(char), BUF_LENGTH,fileS))>0)
                            {
                                printf("entering to the file loop %d \n", varS);
                                if(write(sock, buf_S, varS)<0){
                                printf("erreur");
                                fprintf(stderr, "Cannot send the file %s \n", fileS_path); exit;}

                                bzero(buf_S,BUF_LENGTH);    
                                printf("bzero buffer2\n");
                            }

                            printf("The file was sent from the client to the server\n");
                            if(fileS!=NULL)
                            fclose(fileS);
                            printf("close fileS");

                        }
                    }

                }

                else if(res[0]!=NULL && res[1] !=NULL && strcmp(res[0], "get")==0)
                {
                    if(write(sock, cmd, 4096)<0)
                    printf("problem with sending the socket command \n");
                    else{
                        printf("\n\n");
                        // Receiving file from the server to the client 

                        printf("****RECEIVING****\n");

                        if(getcwd(cwd2,sizeof(cwd2))!=NULL){
                            fileR_path = cwd2;
                            strcat(fileR_path, "/");
                            strcat(fileR_path, res[1]);
                        }               

                        printf("Receiving the file %s from the SERVER...\n", fileR_path);

                        FILE *fileR = fopen(fileR_path, "w");   
                        if(!fileR)
                        fprintf(stderr, "File %s cannot be opened. \n", fileR_path);
                        else
                        {
                            bzero(buf_R,BUF_LENGTH);
                            varR =-1;  varR2 =-1;

                            while((varR=read(sock, buf_R, BUF_LENGTH))>=0)
                            {
                                varR2=fwrite(buf_R, sizeof(char), varR,fileR);
                                if (varR2< varR)
                                fprintf(stderr, "Cannot write the file %s on the client \n", fileR_path);

                                bzero(buf_R,BUF_LENGTH);
                                if(varR == 0 || varR !=BUF_LENGTH)
                                break;
                            }

                            if(varR<0){
                            printf("Receiving failure while reading from the socket\n"); return -8;}

                            printf("The file was received from the SERVER to the CLIENT\n\n");
                            fclose(fileR);
                        }
                    }   

                }


                else if( res[0]!=NULL && strcmp(res[0], "cd\n")==0)
                {
                    if(write(sock, cmd, 4096)<0)
                    printf("Problem with sending the socket command \n");
                    if(read(sock, cwd, sizeof(cwd))<0)
                    printf("Problem reading the current working directory of the server \n");
                    else
                    printf("CWD of the server: %s",cwd); 
                }
                else
                {
                    printf("Wrong command, please try again\n");
                }

            //}
            bzero(cmd, 4096);
            printf("bzero cmd\n");
            /* free the memory allocated */
            free (res); 
            printf("free res\n");
        }   

    }

    /* close socket */
    close(sock);

    printf("exit now\n");
    return 0;
}

服务器端:尝试通过套接字捕获命令。然后,它测试该命令是否为有效命令。例如,如果它是一个 put 命令,它会通过套接字读取来自客户端的流(读取)。然后,打开一个文件并将这些流写入其中。

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/socket.h>
#include <linux/in.h>
#include <unistd.h>
//#include <netinet/in.h> /* struct sockaddr_in, htons() */
//#include <arpa/inet.h> /* inet_aton() */
#include <string.h>

#define BUF_LENGTH 100
#define MAXQ 10

typedef struct
{
    int sock;
    struct sockaddr address;
    int addr_len;
} connection_t;

void * process(void * ptr)
{
    char * buffer;
    int len;
    connection_t * conn;
    long addr = 0;

    char cmd[4096], cmd2[4096];

    char ** res  = NULL;

    char *  p    = strtok (cmd2, " ");
    int n_spaces = 0, i;

    char *fileR_path;
    char cwd[2048];

    char buf_R[BUF_LENGTH];
    FILE * fileR;
    int varR, varR2;

    if (!ptr) pthread_exit(0); 
    conn = (connection_t *)ptr;


    while (1) // (strcmp(res[0],"exit")!=0)
    {
        printf("before reading the socket\n");
        if(read(conn->sock, cmd, 4096)<0)
        printf("Problem with reading the command from the server\n");
        if (cmd ==NULL || strcmp(cmd, "")==0)
        printf("receiving NULL command\n");
        else
        {
            printf("After getting the command %s\n", cmd);

            strcpy(cmd2, cmd);
            p    = strtok (cmd2, " ");
            n_spaces = 0;


            /* split string and append tokens to 'res' */
            while (p) {
              res = realloc (res, sizeof (char*) * ++n_spaces);

              if (res == NULL)
                exit (-1); /* memory allocation failed */

              res[n_spaces-1] = p;

              p = strtok (NULL, " \n");
            }

            /* realloc one extra element for the last NULL */
            res = realloc (res, sizeof (char*) * (n_spaces+1));
            res[n_spaces] = 0;

            /* print the result */
            for (i = 0; i < (n_spaces+1); ++i)
              printf ("res[%d] = %s\n", i, res[i]);


            printf("bar");  
            printf("%s test before sending to socket\n", cmd);

            if((res[0] != NULL) && (res[1] != NULL) && strcmp(res[0],"put")==0)
            {
                /* Receiving File from the client in the server directory */
                printf("\n****RECEIVING****\n");

                if(getcwd(cwd,sizeof(cwd))!=NULL){
                fileR_path = cwd;
                strcat(fileR_path, "/");
                strcat(fileR_path, res[1]);}

                printf("Receiving the file %s from the client...\n", fileR_path);

                fileR = fopen(fileR_path, "w");
                if(fileR==NULL)
                fprintf(stderr, "File %s cannot be opened. \n", fileR_path);
                else
                {
                    bzero(buf_R, BUF_LENGTH);
                    varR =-1 ; varR2=-1;

                    while((varR=read(conn->sock, buf_R, BUF_LENGTH))>=0)
                    {
                        varR2=fwrite(buf_R, sizeof(char), varR,fileR);
                        if (varR2< varR){
                        fprintf(stderr, "Cannot write the file %s on the server \n", fileR_path); exit;}

                        bzero(buf_R,BUF_LENGTH);

                        if((varR == 0 ) || (varR !=BUF_LENGTH)){
                        //printf("Something wrong with reading the socket \n"); 
                            break;

                        }
                    }   



                    if(varR<0){
                        printf("Receiving failure due to error in reading socket\n"); 
                        //break;
                        exit;
                    }

                    printf("The file was received from the client to the server\n");

                    if(fileR!=NULL){

                    fclose(fileR);
                    printf("fileR closed\n");}

                }



                printf("\n");
            }

            else if ((res[0] != NULL) && (res[1] != NULL) && strcmp(res[0], "get")==0)
            {   
                // Sending file from the server to the client 

                printf("\n****SENDING****\n");
                char *fileS_path; 
                char cwd2[2048];
                if(getcwd(cwd2,sizeof(cwd2))!=NULL){
                    fileS_path=cwd2;
                    strcat(fileS_path, "/");
                    strcat(fileS_path, res[1]);
                }
                char buf_S[BUF_LENGTH];

                printf("Sending the file %s to the CLIENT...\n", fileS_path);

                FILE *fileS = fopen(fileS_path, "r");
                if(!fileS)
                fprintf(stderr, "File %s is not found. \n", fileS_path);
                else
                {
                    bzero(buf_S,BUF_LENGTH);
                    int varS;

                    while((varS=fread(buf_S, sizeof(char), BUF_LENGTH,fileS))>0)
                    {
                        if(write(conn->sock, buf_S, varS)<0){
                        fprintf(stderr, "Cannot send the file %s \n", fileS_path); break;}

                        bzero(buf_S,BUF_LENGTH);        
                    }

                    printf("The file was sent from the SERVER to the CLIENT\n\n");
                    fclose(fileS);
                }

            }

            else if (res[0]!=NULL && strcmp(res[0], "cd\n")==0)
            {
                if(getcwd(cwd,sizeof(cwd))!=NULL){
                    if(write(conn->sock, cwd, sizeof(cwd))<0){
                    printf("Cannot send the current working directory \n");
                    }
                }
            }

            else if (strcmp(res[0], "quit")==0)
            exit; //break;

            bzero(cmd, 4096);
            printf("bzerocmd\n %s", cmd);
            free(res);
            printf("free res\n");
        }

    }
    /* close socket and clean up */
    close(conn->sock);
    printf("socket closed\n");
    free(conn);
    printf("Connection free\n");
    pthread_exit(0);
    printf("Thread exit\n");
}

int main(int argc, char ** argv)
{
    int sock = -1;
    struct sockaddr_in address;
    int port;
    connection_t * connection;
    pthread_t thread;

    /* check for command line arguments */
    if (argc != 2)
    {
        fprintf(stderr, "usage: %s port\n", argv[0]);
        return -1;
    }

    /* obtain port number */
    if (sscanf(argv[1], "%d", &port) <= 0)
    {
        fprintf(stderr, "%s: error: wrong parameter: port\n", argv[0]);
        return -2;
    }

    /* create socket */
    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock <= 0)
    {
        fprintf(stderr, "%s: error: cannot create socket\n", argv[0]);
        return -3;
    }

    /* bind socket to port */
    bzero(&address, sizeof(address));
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = htonl(INADDR_ANY);
    address.sin_port = htons(port);
    if (bind(sock, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) < 0)
    {
        fprintf(stderr, "%s: error: cannot bind socket to port %d\n", argv[0], port);
        return -4;
    }

    /* listen on port */
    if (listen(sock, MAXQ) < 0)
    {
        fprintf(stderr, "%s: error: cannot listen on port\n", argv[0]);
        return -5;
    }

    printf("%s: ready and listening\n", argv[0]);

    while (1)
    {
        /* accept incoming connections */
        connection = (connection_t *)malloc(sizeof(connection_t));
        connection->sock = accept(sock, &connection->address, &connection->addr_len);
        if (connection->sock <= 0)
        {
            free(connection);
        }
        else
        {
            /* start a new thread but do not wait for it */
            pthread_create(&thread, 0, process, (void *)connection);
            pthread_detach(thread);
        }
    }

    return 0;
}

这里的问题,以 put 命令为例(然而,它对于 get 命令是一样的),在第一次迭代中一切都很好。文件被复制,程序看起来很好。但是,在第二次迭代中(我的意思是当我在客户端第二次输入命令时)文件被复制到服务器端,并且在双方(服务器和客户端)都显示分段错误。我试图了解这个分段错误是从哪里来的,所以发现程序在 fclose 函数处停止。我不明白为什么?有什么帮助吗?

4

0 回答 0