2015-11-29 2 views
0

Я закодировал приложение, в котором клиент отправляет файл на сервер с сокетом, который использует протокол tcp.socket отправляет файл клиент-сервер

Мой сервер многопоточный (с Pthread).

Есть только одна проблема, скопировать файл на сервер меньше (около 2ko loss) в качестве исходного файла. Зачем?

Вот мой код клиента, который начинает набирать ./client имя файла filenamecopy

#include <netdb.h> 
#include <netinet/in.h> 
#include <string.h> 
#include <stdio.h> 
  
  
int fileSEND(char *server, int PORT, char *lfile, char *rfile){ 
  
    int socketDESC; 
    struct sockaddr_in serverADDRESS; 
    struct hostent *hostINFO; 
    FILE * file_to_send; 
    int ch; 
    char toSEND[1]; 
    char remoteFILE[4096]; 
    int count1=1,count2=1, percent; 
  
    hostINFO = gethostbyname(server); 
    if (hostINFO == NULL) { 
        printf("L'adresse ip du serveur n'est pas accesible\n"); 
        return 1; 
    } 
  
    socketDESC = socket(AF_INET, SOCK_STREAM, 0); 
    if (socketDESC < 0) { 
        printf("Erreur création socket\n"); 
        return 1; 
    } 
  
    serverADDRESS.sin_family = hostINFO->h_addrtype; 
    memcpy((char *) &serverADDRESS.sin_addr.s_addr, hostINFO->h_addr_list[0], hostINFO->h_length); 
    serverADDRESS.sin_port = htons(PORT); 
  
    if (connect(socketDESC, (struct sockaddr *) &serverADDRESS, sizeof(serverADDRESS)) < 0) { 
        printf("Erreur de connection\n"); 
        return 1; 
    } 
  
  
    file_to_send = fopen (lfile,"r"); 
    if(!file_to_send) { 
        printf("Erreur de lecture du fichier\n"); 
        close(socketDESC); 
        return 0; 
    } else { 
    long fileSIZE; 
    fseek (file_to_send, 0, SEEK_END); fileSIZE =ftell (file_to_send); 
    rewind(file_to_send); 
  
    sprintf(remoteFILE,"FBEGIN:%s:%i\r\n", rfile, fileSIZE); 
    send(socketDESC, remoteFILE, sizeof(remoteFILE), 0); 
  
    percent = fileSIZE/100; 
    while((ch=getc(file_to_send))!=EOF){ 
        toSEND[0] = ch; 
        send(socketDESC, toSEND, 1, 0); 
        if(count1 == count2) { 
            printf("33[0;0H"); 
            printf("\33[2J"); 
            printf("Nom du fichier: %s\n", lfile); 
            printf("Taille du fichier: %i Kb\n", fileSIZE/1024); 
            printf("Poucentage : %d%% (%d Kb)\n",count1/percent ,count1/1024); 
            count1+=percent; 
        } 
        count2++; 
  
    } 
    } 
    fclose(file_to_send); 
    close(socketDESC); 
return 0; 
} 
  
int main(int argc, char* argv[]) 
{ 
    fileSEND("127.0.0.1", 31338, argv[1], argv[2]); 
    return 0; 
} 

и сервер, который запускается только ./server

#include <arpa/inet.h> 
#include <netdb.h> 
#include <netinet/in.h> 
#include <string.h> 
#include <stdio.h> 
#include <pthread.h> 
  
#define PORT 31338 
  
int parseARGS(char **args, char *line){ 
    int tmp=0; 
    args[tmp] = strtok(line, ":"); 
    while ((args[++tmp] = strtok(NULL, ":")) != NULL); 
    return tmp - 1; 
} 
  
int client(void *ptr){ 
    int  connectSOCKET; 
    connectSOCKET = (int) ptr; 
    char recvBUFF[4096]; 
    char *filename, *filesize; 
    FILE * recvFILE; 
    int received = 0; 
    char tempstr[4096]; 
    char *header[4096]; 
  
    /*int i=0; 
    while(i<993199) { 
    i++;*/ 
    while(1){ 
        if(recv(connectSOCKET, recvBUFF, sizeof(recvBUFF), 0)){ 
            if(!strncmp(recvBUFF,"FBEGIN",6)) { 
                recvBUFF[strlen(recvBUFF) - 2] = 0; 
                parseARGS(header, recvBUFF); 
                filename = header[1]; 
                filesize = header[2]; 
                printf("Fichier: %s\n", filename); 
                printf("Taille: %d Kb\n", atoi(filesize)/1024); 
        } 
        recvBUFF[0] = 0; 
        recvFILE = fopen (filename,"w"); 
        while(1){ 
            if(recv(connectSOCKET, recvBUFF, 1, 0) != 0) { 
                fwrite (recvBUFF , sizeof(recvBUFF[0]) , 1 , recvFILE); 
                received++; 
                recvBUFF[0] = 0; 
                } else { 
                printf("Progression: %s [ %d of %s bytes]\n", filename, received , filesize); 
                return 0; 
                } 
            } 
            return 0; 
        } else { 
        printf("Client déconnecté\n"); 
        } 
    return 0; 
    } 
} 
  
  
int main() 
{ 
    int socketINDEX = 0; 
    int listenSOCKET, connectSOCKET[4096]; 
    socklen_t clientADDRESSLENGTH[4096]; 
    struct sockaddr_in clientADDRESS[4096], serverADDRESS; 
    pthread_t threads[4096]; 
  
    listenSOCKET = socket(AF_INET, SOCK_STREAM, 0); 
    if (listenSOCKET < 0) { 
        printf("Peut pas crée socket\n"); 
        close(listenSOCKET); 
        return 1; 
    } 
  
    serverADDRESS.sin_family = AF_INET; 
    serverADDRESS.sin_addr.s_addr = htonl(INADDR_ANY); 
    serverADDRESS.sin_port = htons(PORT); 
  
    if (bind(listenSOCKET, (struct sockaddr *) &serverADDRESS, sizeof(serverADDRESS)) < 0) { 
        printf("Peut pas trouver la socket\n"); 
        close(listenSOCKET); 
        return 1; 
    } 
  
    listen(listenSOCKET, 5); 
    clientADDRESSLENGTH[socketINDEX] = sizeof(clientADDRESS[socketINDEX]); 
    int i=0; 
    /*while(i<993199) { 
    i++;*/ 
    while(1){ 
        connectSOCKET[socketINDEX] = accept(listenSOCKET, (struct sockaddr *) &clientADDRESS[socketINDEX], &clientADDRESSLENGTH[socketINDEX]); 
        if (connectSOCKET[socketINDEX] < 0) { 
            printf("Connection refusé\n"); 
            close(listenSOCKET); 
            return 1; 
        } 
  
        pthread_create(&threads[socketINDEX], NULL, client, connectSOCKET[socketINDEX]); 
        if(socketINDEX=4096) { 
            socketINDEX = 0; 
        } else { 
        socketINDEX++; 
        } 
    } 
    close(listenSOCKET); 
} 
+0

Не могли бы вы еще раз объяснить эту проблему? –

ответ

0

две проблемы:

  1. Ваш клиент отправляет блок 4K с заголовком FBEGIN: filename: size. Сервер пытается прочитать его в одном блоке 4K. recv() может возвращать меньше, чем полный буфер (всего 1 байт).

  2. Ваш сервер не закрывает файл после его чтения. Вероятно, это приводит к несоответствию размера файла (буферизованные данные будут очищены при закрытии файла).

не ошибка сама по себе, но проблема производительности: чтение/запись/отправка/прием один байт в то время S-L-О-З. Вы должны делать все в больших блоках (даже 1K будет огромным усилением). Просто имейте в виду, что «recv() может завершить частично» проблему, упомянутую выше.

+0

Хорошо, спасибо за ваш ответ. 1) Я должен изменить 4096 на 1024? 2) Я не отключаю, что хочу добавить fclose (recvFILE); после закрытия (listenSOCKET); ? – sazearte

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