I have an application for transferring files from clients to a server. A client opens, transfers a file to the server and closes. The server is open and may receive multiple files. Also, when transferring a file, a loader bar is created on both server (the server must have some way to display multiple loaders simultaneously) and client. Also, every file transfer is handled in a separate thread on server. This is a structure that will be used in server function:struct fileWriteArgs{    int childNumber;    int sockfd;};Here is the server function (the main function just parses arguments and calls this):int serverFileTransfer(int port, char* filename){    int sockfd = socket(AF_INET, SOCK_STREAM, 0);    if(sockfd<0)        errorOpeningSocket();    struct sockaddr_in serv_addr, cli_addr;    memset((char*) &serv_addr, 0, sizeof(serv_addr));    serv_addr.sin_family = AF_INET;    serv_addr.sin_port = htons(port);    serv_addr.sin_addr.s_addr = INADDR_ANY;    if(bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)        errorOnBinding();    listen(sockfd, 5);    socklen_t cilen = sizeof(cli_addr);    pthread_t newThread;    pthread_attr_t attr;    pthread_attr_init(&attr);    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);    int noOfChilds = 0;    while(1){        int newsockfd = accept(sockfd, (struct sockaddr*)&cli_addr, &cilen);        noOfChilds++;        struct fileWriteArgs args;        args.sockfd = newsockfd;        args.childNumber = noOfChilds;        if(newsockfd < 0)            errorOnAccept();        pthread_create(&newThread, &attr, &fileWrite, &args);    }    pthread_attr_destroy(&attr);    return 0;}Basically, it opens a socket and creates threads for file accept (note that I am using a Linux operating system). Also, it calls some error functions that I think are pretty explicit (they just write a message and call exit()).Here are the loader and fileWrite functions:void loader(int val, int max, int size, int row){    static int lastPrinted = 0;    int percent = (100.*val)/max;    int count = ((float)percent * size) / 100;    if(count == lastPrinted)        return;    if(row > 0){        printf(\033[s); //save current position        printf(\033[%dB\n, row);    }    lastPrinted = count;    printf(\r[);    int i;    for(i = 0; i < count; i++)        printf(#);    for(; i < size; i++)        printf(.);    printf(] %d%%, percent);    if(row > 0)        printf(\033[u);    fflush(stdout);}static pthread_mutex_t STDOUT_mutex = PTHREAD_MUTEX_INITIALIZER;void* fileWrite(void *fd){    struct fileWriteArgs *p = (struct fileWriteArgs*)fd;    int sockfd = p->sockfd;    int childNumber = p->childNumber;    char sz[32];    read(sockfd, sz, 32);    int fileSize = atoi(sz);    char fileNameSize;    int readed = read(sockfd, &fileNameSize, 1);    if(readed < 0)        errorReadingFromSocket();    else if(fileNameSize == 0)        errorBadFileName();    char filename[256];    readed = read(sockfd, filename, fileNameSize);    if(readed < 0)        errorReadingFromSocket();    FILE *f = fopen(filename, wb);    if(f == NULL){        errorOpeningFile();    }    char buffer[BUFFER_SIZE];    int n = 0;    while(n < fileSize){        readed = read(sockfd, buffer, BUFFER_SIZE);        if(readed < 0)            errorReadingFromSocket();        write(fileno(f), buffer, readed);        n += readed;        pthread_mutex_lock(&STDOUT_mutex);        loader(n, fileSize, LOADER_LENGTH, childNumber);        pthread_mutex_unlock(&STDOUT_mutex);    }    fclose(f);    return NULL;}This is the client function:int clientFileTransfer(char *ip, int port, char* filename){    int sockfd = socket(AF_INET, SOCK_STREAM, 0);    if(sockfd < 0)        errorOpeningSocket();    struct hostent* server = gethostbyname(ip);    if(server == NULL)        noServerFound();    struct sockaddr_in serv_addr;    memset((char*)&serv_addr, 0, sizeof(serv_addr));    serv_addr.sin_family = AF_INET;    serv_addr.sin_port = htons(port);    bcopy((char*) server -> h_addr, (char*) &serv_addr.sin_addr.s_addr, server -> h_length);    if(connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)        errorConnecting();    fileRead(filename, sockfd);    return 0;}And the fileRead function:void fileRead(char *filename, int sockfd){    FILE *f = fopen(filename, rb);    if(f == NULL){        errorOpeningFile();        return;    }    fseek(f, 0, SEEK_END);    int fileSize = ftell(f);    fseek(f, 0, SEEK_SET);    char size[32];    sprintf(size, %d, fileSize);    write(sockfd, size, 32);    char *name = strrchr(filename, '/');    if(name == NULL)        name = filename;    else        name++;    char fileNameSize = strlen(name)+1;    write(sockfd, &fileNameSize, 1);  //WARNING! it works only for files                                           //with at most 255 characters    write(sockfd, name, strlen(name)+1);    int n = 0; //total bytes read/written    char buffer[BUFFER_SIZE];    while(!feof(f)){        int read = fread(buffer, 1, BUFFER_SIZE, f);        if(read < 0)            errorReadingFromFile();        write(sockfd, buffer, read);        n+=read;        loader(n, fileSize, LOADER_LENGTH, 0);    }    fclose(f);}The clientFileTransfer and fileRead functions are used by the client in a similar manner to serverFileTransfer and fileWrite, that are used by server. As the code is pretty large, I would like some parts to be reviewed especially, as I feel there is something wrong there. My primary concern is the loader function. It has a static variable that keeps the value that was written last time when the function was called (to avoid printing the same thing all over again). I do not know if this is a good thing. Also this is my first multithreaded application, so I would like some remarks about the way that multithreading is implemented here.Of course, I would really appreciate if I get also a review of the other parts of this application and remarks about it (what I have done right and where something is wrong).
Client server application for file transfer
c;multithreading;file;server
Nice code in general.  Many of my comments are a bit on thenit-picking level, so apologies in advance.Your method of error handling seems to be just to exit, so the returnvalues from various functions should probably be void.  This methodof error handling is certainly easy but might be considered lazy :-) Inotice that you don't check for EINTR in any failed socket calls -should it not be handled?Some of the variable names are too long for my taste.  newsockfdfor example in the accept loop could be just fd with no loss. In fileRead and fileWriteThese functions seem misnamed.  Clearly one does read a file and onewrites but I think names containing 'send' and 'receive' would beclearer.  Having clientFileTransfer 'connect' to the server socketand then do a fileRead implies to me that it is receiving a filewhen in fact it is sending!Some details I noticed are that fileNameSize should be unsigned ifyou want to handle names up to 255 chars long.  And it would be betterto reject files with names longer than 255 instead of just adding awarning comment.unsigned char fileNameSize = strlen(name)+1;write(sockfd, &fileNameSize, 1);  //WARNING! it works only for files                                  //with at most 255 characterswrite(sockfd, name, strlen(name)+1);In the fileRead code above you could re-use fileNameSize in thelast write call rather than repeating the strlen call.  And yourread and write calls here and elsewhere should really all beerror-checked (some are, some are not).When writing the file to disk, I don't see a good reason for openingthe file buffered (fopen from stdio) but writing un-buffered(write) - I would use fwrite.A minor point is that the 32 used as the file-size buffer char sz[32];read(sockfd, sz, 32);int fileSize = atoi(sz);should really be a constant defined in a header shared between clientand server.  And I would use it just once:char sz[SIZE_BUFFER_SIZE];read(sockfd, sz, sizeof sz);  // use sizeofint fileSize = atoi(sz);In serverFileTransfer the filename parameter is not used.  Iwould expect to see the check for the accepted socket being invalidimmediately after the accept call.  Also this socket is never closed(not here and not in the fileWrite thread.In clientFileTransfer the socket is not closed.