【问题标题】:problem of sending structure with fwrite() TCP Server client使用 fwrite() TCP Server 客户端发送结构的问题
【发布时间】:2022-01-23 03:32:19
【问题描述】:

我有一个帐户结构(如银行帐户),我想在应用程序启动时写“状态”时将帐户信息发送给客户端:./client state 然后服务器必须发送信息客户端,但是我在使用 fwrite 函数发送结构时遇到问题, 我已经在我的服务器上实现了这个。c

...
if(strcmp(buffer, "state") == 0) {
            printf("sending the state of account...\n");
            memcpy(buffer, &a1, sizeof(a1));
            printf("%s\n", buffer);
            size_t nb_write = fwrite(buffer, sizeof(char), sizeof(MAX_BUFF), client_array[0].file);
            printf("number i write: %ld\n", nb_write);
            if(fflush(client_array[0].file)){
                syserr("error of fflush");
            }
        }

在我的 client.c 上我写了这个:

...
 if(argc > 1){
        printf("argv[1]: %s\n", argv[1]);
        size_t nb_write = fwrite(argv[1], sizeof(*argv), strlen(argv[1]), fdc);
    
        printf("number i write: %ld\n", nb_write);
    
        if(fflush(fdc)){
            syserr("fflush");
        }
    }
    size_t nbread = fread(&buffer, strlen(buffer), sizeof(BUFF_SIZE), fdc); // reception of structure
    printf("number i read: %ld\n", nbread);
    printf("%s\n", buffer);

应用客户端正在等待 fread()

./server的输出:

number i read: 4
state
sending the state of account...
account 1
number i write: 4
error of fflush: Illegal seek

当我按 CTRL-C 停止服务器时,应用程序客户端写了一些奇怪的东西(可能是缓冲区的内容)并且应用程序也停止了。

Socket creation successful
Connection successful !
argv[1]: state
number i write: 5
number i read: 0
��E-�

这里是我要发送的结构:

    struct account{
        char title[MAX_TITLE_LENGTH];
        struct user list_user[MAX_LIST_SIZE];
        // char description[140]; // for example hotel, market, travel
        int32_t total;
    };
    
    struct account a1;
    /* ACCOUNT */
    strcpy(a1.title, "account 1");
    a1.list_user[0] = u1;
    a1.total = 0.0;

如何修复它以在客户端的 fd 上正确发送结构并在客户端的缓冲区中读取它

【问题讨论】:

    标签: c sockets server tcp client


    【解决方案1】:

    我看到这段代码中有很多错误:

    • 服务器的fwrite() 中的sizeof(MAX_BUFF) 是错误的。您只需使用MAX_BUFFsizeof(buffer)

    • 客户端的fwrite() 中的sizeof(*argv) 是错误的。 *argv(又名argv[0])是char*,而不是char。您需要改用sizeof(char)1

    • 客户端没有向服务器发送命令的空终止符或命令的长度,那么您如何期望服务器知道何时到达命令的末尾? TCP 中的写入和读取之间没有 1:1 的关系,因此您必须以一种或另一种方式考虑数据的实际大小。

    • 当客户端调用fread()&bufferstrlen(buffer)sizeof(BUFF_SIZE)都是错误的。虽然&buffer 可能有效,但strlen(buffer) 肯定不会,因为buffer 尚未填充以空字符结尾的字符串,因此您需要使用sizeof(char)1。而sizeof(BUFF_SIZE) 必须是BUFF_SIZEsizeof(buffer)

    • 客户端和服务器中的printf("%s\n", buffer); 都是错误的,因为buffer 显然不是以null 结尾的字符串。

    • 即使客户端没有请求服务器发送它,客户端也希望接收到该结构。

    话虽如此,请尝试更多类似的东西:

    ...
    char *cmd = NULL;
    size_t size;
    ssize_t len;
    
    if ((len = getdelim(&cmd, &size, '\0', client_array[0].file)) < 0) {
        syserr("error of getdelim");
        fclose(client_array[0].file);
    }
    else if (strcmp(cmd, "state") == 0) {
        printf("sending the state of account...\n");
        uint32_t size = htonl(sizeof(a1));
        size_t nb_write = fwrite(&size, sizeof(size), 1, client_array[0].file);
        if (nb_write == 1) {
            nb_write = fwrite(&a1, sizeof(a1), 1, client_array[0].file);
        }
        if (nb_write < 1) {
            syserr("error of fwrite");
            fclose(client_array[0].file);
        }
        else {
            printf("number i write: %ld\n", sizeof(size) + sizeof(a1));
            if (fflush(client_array[0].file) != 0) {
                syserr("error of fflush");
            }
        }
    }
    free(cmd);
    
    ...
    if (argc > 1) {
        printf("argv[1]: %s\n", argv[1]);
    
        if (fwrite(argv[1], strlen(argv[1])+1, 1, fdc) < 1) {
            syserr("error of fwrite");
            fclose(fdc);
        }
        else if (fflush(fdc) != 0) {
            syserr("fflush");
        }
    
        uint32_t size;
        size_t nb_read = fread(&size, sizeof(size), 1, fdc);
        if (nb_read == 1) {
            size = ntohl(size);
            nb_read = fread(buffer, size, 1, fdc);
        }   
        if (nb_read < 1) {
            syserr("error of fread");
            fclose(fdc);
        }
        else {
            printf("number i read: %ld\n", sizeof(size) + size);
            printf("%.*s\n", size, buffer);
        }
    }
    

    【讨论】:

    • 这是一个很好的解决方案,但不适用于我的代码,我认为客户端 fd 的读取也不起作用。
    • 注意:fdcFILE*,而不是简单的int fdc
    • "不使用我的代码" - 你必须更具体。 “读取客户端 fd 也不起作用” - 为什么不呢?实际问题是什么? “注意:fdcFILE*,而不是简单的 int fdc” - 好的,这仅影响了 close() 调用,我现在已将其更改为 fclose()。跨度>
    • 我必须做 CTRL-C 才能看到服务器和客户端移动的东西,实际问题是服务器读取“状态”这个词,现在我不工作'不明白为什么
    猜你喜欢
    • 1970-01-01
    • 2018-08-02
    • 2018-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-26
    相关资源
    最近更新 更多