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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C中的服务器/套接字编程:数据未正确发送/接收?相关的知识,希望对你有一定的参考价值。

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

客户端这样做:

  1. 获取.csv文件的文件大小
  2. 将filesize发送到服务器
  3. 打开.csv
  4. 使用fgets()检索一行并将其放入缓冲区
  5. 将此行的字节数发送到服务器
  6. 将该行的数据发送到服务器

目标是逐行发送数据,并将每一行存储在服务器端的结构中。问题是,数据没有被发送过来。似乎单个发送请求被切断并在两个不同的recv()调用中处理。

客户端发送循环:

void sendData(int sock, FILE* fd){
    char data[BUFFER];
    int32_t filesize;

    printf("seeking
");
    if((fseek(fd, 0L, SEEK_END)) == ERROR){
        fprintf(stderr, "An error has occured: %s
", strerror(errno));
        exit(EXIT_FAILURE);
    };
    if((filesize = ftell(fd)) == ERROR){
        fprintf(stderr, "An error has occured: %s
", 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
", (int)strlen(data));
    printf("
filesize: %ld
", (long)filesize);
    filesize = filesize - strlen(data);
    printf("
filesize: %ld
", (long)filesize);
    // converting data len to net order
    filesize = htonl(filesize);
    char* len_data = (char*)&filesize;
    // sending filesize
    printf("sending filesize
");
    send(sock, len_data, sizeof(int32_t), 0);
    filesize = ntohl(filesize);
    printf("
filesize: %ld
", (long)filesize);

    // grabbing first line and sending
    //printf("fgetting test
");
    while(filesize > 0){
        while(fgets(data, sizeof(data), fd) != NULL){
            if(data[strlen(data) - 1] == '
'){
                printf("
taking newline out
");
                data[strlen(data) - 1] = '';
            }

            // getting and sending size of the line
            int32_t dataSize = sizeof(char)*strlen(data);
            printf("data size of line: %d
", dataSize);
            dataSize = htonl(dataSize);
            char* lineSize = (char*)&dataSize;
            int j = send(sock, lineSize, sizeof(int32_t), 0);
            printf("size of data sent: %d
", j);

            // sending the line
            printf("line of data: %s
", data);
            int i = send(sock, data, sizeof(char)*strlen(data), 0);
            printf("size of data sent: %d
", i);
            filesize -= i;
            printf("new filesize: %d
", 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
", filesize);
    // wait for a recv
    while(filesize){

        printf("
Current File Size: %ld
",(long) filesize);
        receive_int(&linesize,sock_info->sock);
        printf("Line size: %ld
", (long)linesize);
        char* filebuf = (char*)malloc(sizeof(char)*linesize);
        printf("size of filebuf: %d
", sizeof(*filebuf));
        int i = recv(sock_info->sock, filebuf, sizeof(char)*linesize, 0);
        printf("strlen of filebuf: %d
", strlen(filebuf));
        printf("number of bytes received: %d
", i);
        printf("Received msg: %s
",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
答案

正如manrecv页面所示:

接收呼叫通常会返回任何可用的数据,直到请求的数量,而不是等待收到所请求的全部金额。

正如mansend页面所示:

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

正如manwrite页面所示:

写入从缓冲区计数字节从...开始

如您所见,网络sendrecv不保证实际发送的数据长度或每个函数调用中接收的数据长度。

此外,随着分组在网络中移动,将单个分组分段为多个分组(例如,由于网络MTU设置的差异),这是非常常见的。

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

为了找到新的线标记,接收端点必须连接任何接收的数据并沿着新的线标记切断。

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

祝好运。

以上是关于C中的服务器/套接字编程:数据未正确发送/接收?的主要内容,如果未能解决你的问题,请参考以下文章

通过 C 中的套接字快速接收不同长度数据包的连续流?

Python 3套接字客户端发送数据和C++套接字服务器接收偏移数据?

通过 C 中的套接字传递结构

在 C++ 套接字编程中嵌入 Python

是发送还是接收错误?未发送完整消息或未正确解码消息

缓冲读取器未从套接字接收数据