套接字发送客户端 - 服务器文件

时间:2015-11-29 08:33:15

标签: c sockets pthreads

我编写了一个应用程序,其中客户端使用使用tcp协议的套接字将文件发送到服务器。

我的服务器是多线程的(使用Pthread)。

只有一个问题,将文件复制到服务器较小(约2ko丢失)作为原始文件。为什么呢?

这是我的客户端代码,它开始输入./client filename 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);
}

1 个答案:

答案 0 :(得分:0)

两个问题:

  1. 您的客户端发送带有FBEGIN:filename:size标头的4K块。服务器尝试在一个4K块中读取它。 recv()可以返回少于一个完整的缓冲区(最少1个字节)。

  2. 您的服务器在读取后不会关闭该文件。这可能导致文件大小不一致(当文件关闭时,缓冲的数据将被刷新)。

  3. 本身不是错误,但是性能问题:一次读取/写入/发送/接收一个字节 S-L-O-W 。你应该用更大的块来做任何事情(即使只有1K也会是一个巨大的性能提升)。请记住上面提到的“recv()可能部分完成”问题。

相关问题