C中的服务器/套接字编程:数据未正确发送/接收?

时间:2017-12-16 04:08:22

标签: c sockets server

我正在编写一个侦听连接的服务器端程序。当它收到一个时,它会产生一个分离的线程并处理连接。我希望它能够接收从客户端发送的几行数据,并将其存储在数据结构中(所以我可以稍后对其进行排序)。

客户端执行此操作:

  1. 获取.csv文件的文件大小
  2. 将文件大小发送到服务器
  3. 打开.csv
  4. 使用fgets()检索一行并将其放入缓冲区
  5. 将此行的字节数发送到服务器
  6. 将该行的数据发送到服务器
  7. 目标是逐行发送数据,并将每一行存储在服务器端的结构中。问题是,数据没有被发送过来。似乎单个发送请求被切断并在两个不同的recv()调用中处理。

    客户端发送循环:

    void sendData(int sock, FILE* fd){
        char data[BUFFER];
        int32_t filesize;
    
        printf("seeking\n");
        if((fseek(fd, 0L, SEEK_END)) == ERROR){
            fprintf(stderr, "An error has occured: %s\n", strerror(errno));
            exit(EXIT_FAILURE);
        };
        if((filesize = ftell(fd)) == ERROR){
            fprintf(stderr, "An error has occured: %s\n", strerror(errno));
            exit(EXIT_FAILURE);
        };
        rewind(fd);
    
        // subtracting bytes for the col headers 
        //filesize -= COLSIZE;
        fgets(data, sizeof(data), fd);
        printf("strlen of data: %d\n", (int)strlen(data));
        printf("\nfilesize: %ld\n", (long)filesize);
        filesize = filesize - strlen(data);
        printf("\nfilesize: %ld\n", (long)filesize);
        // converting data len to net order
        filesize = htonl(filesize);
        char* len_data = (char*)&filesize;
        // sending filesize
        printf("sending filesize\n");
        send(sock, len_data, sizeof(int32_t), 0);
        filesize = ntohl(filesize);
        printf("\nfilesize: %ld\n", (long)filesize);
    
        // grabbing first line and sending
        //printf("fgetting test\n");
        while(filesize > 0){
            while(fgets(data, sizeof(data), fd) != NULL){
                if(data[strlen(data) - 1] == '\n'){
                    printf("\ntaking newline out\n");
                    data[strlen(data) - 1] = '\0';
                }
    
                // getting and sending size of the line
                int32_t dataSize = sizeof(char)*strlen(data);
                printf("data size of line: %d\n", dataSize);
                dataSize = htonl(dataSize);
                char* lineSize = (char*)&dataSize;
                int j = send(sock, lineSize, sizeof(int32_t), 0);
                printf("size of data sent: %d\n", j);
    
                // sending the line
                printf("line of data: %s\n", data);
                int i = send(sock, data, sizeof(char)*strlen(data), 0);
                printf("size of data sent: %d\n", i);
                filesize -= i;
                printf("new filesize: %d\n", filesize);
            }
        }
    

    客户输出:

    taking newline out
    data size of line: 303                                                                                               
    size of data sent: 4                                                                                                 
    line of data: Color,Andrew Stanton,462,132,475,530,Samantha Morton,640,73058679,Action|Adventure|Sci-Fi,Daryl Sabara,John Carter ,212204,1873,Polly Walker,1,alien|american civil war|male nipple|mars|princess,http://www.imdb.com/title/tt0401729/?ref_=fn_tt_tt_1,738,English,USA,PG-13,263700000,2012,632,6.6,2.35,24000
    size of data sent: 303
    new filesize: 1001
    

    服务器接收循环:

        int32_t linesize;
        int32_t filesize;
        // set to 1 to attempt to receive bytes
        receive_int(&filesize,sock_info->sock);
        printf("Recieving file size %d\n", filesize);
        // wait for a recv
        while(filesize){
    
            printf("\nCurrent File Size: %ld\n",(long) filesize);
            receive_int(&linesize,sock_info->sock);
            printf("Line size: %ld\n", (long)linesize);
            char* filebuf = (char*)malloc(sizeof(char)*linesize);
            printf("size of filebuf: %d\n", sizeof(*filebuf));
            int i = recv(sock_info->sock, filebuf, sizeof(char)*linesize, 0);
            printf("strlen of filebuf: %d\n", strlen(filebuf));
            printf("number of bytes received: %d\n", i);
            printf("Received msg: %s\n",filebuf);
            filesize -= i;
    
    
        }
    

    服务器输出

    Current File Size: 1304                                                                                              
    Line size: 303                                                                                                       
    size of filebuf: 1                                                                                                   
    strlen of filebuf: 165                                                                                               
    number of bytes received: 165                                                                                        
    Received msg: Color,Andrew Stanton,462,132,475,530,Samantha Morton,640,73058679,Action|Adventure|Sci-Fi,Daryl Sabara,John Carter ,212204,1873,Polly Walker,1,alien|american civil                          
    
    Current File Size: 1139                                                                                              
    Line size: 2002875004                                                                                                
    size of filebuf: 1                                                                                                   
    strlen of filebuf: 134                                                                                               
    number of bytes received: 1139
    Received msg: male nipple|mars|princess,http://www.imdb.com/title/tt0401729/?ref_=fn_tt_tt_1,738,English,USA,PG-13,263700000,2012,632,6.6,2.35,24000
    

1 个答案:

答案 0 :(得分:2)

man的{​​{1}}页所示:

  

接听电话通常会返回所有可用数据,最多可达到所要求的金额,而非等待收到所需的全额金额

recv的{​​{1}}页所示:

  

使用零标志参数,send()等效于write(2)。   ...   成功时,这些调用将返回发送的字节数

man的{​​{1}}页所示:

  

从......

开始的缓冲区中写入最多计数字节

如您所见,网络 sendman无法保证实际发送的数据长度或每次函数调用中收到的数据长度

此外,当数据包通过网络传输时,通常会将单个数据包分段为多个数据包(例如,由于网络MTU设置的差异),这是非常常见的。

处理网络数据的唯一方法是连续流。

为了找到换行符号,接收端点必须连接任何接收的数据并沿着换行符标记它。

我建议Beej's guide作为启动网络编码的良好资源。

祝你好运。