繁体   English   中英

简单的客户端/服务器问题,文件打印错误

[英]Problem with simple Client/Server, file gets printed wrong

基本上,服务器需要将一个由客户端填充的结构打印到文件中,当message.fine == 1时,客户端和服务器都应该停止。问题是每次创建文件时,它都会被数千个零填充,表示读写功能无法正常工作。 你能帮我解决这个问题吗?

这是客户:

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <pthread.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

struct Data 
{
    int a;
    float b;
    int fine;
    int risultato;
};

int main()
{   
    int sock;
    struct Data message, response;
    message.fine = 0;

    struct sockaddr_in address;
    address.sin_family = AF_INET;
    address.sin_port = htons(6869);
    address.sin_addr.s_addr = inet_addr("127.0.0.1");

    sock = socket(AF_INET, SOCK_STREAM, 0);

    connect(sock, (struct sockaddr *)&address, sizeof(address));

    while(message.fine != 1)
    {   
        printf("\nInsert an integer number:");
        scanf("%d", &message.a);
        printf("\nInsert a float number:");
        scanf("%f", &message.b);
        printf("\nIs this the final message? (0 = no, 1 = yes)\n");
        scanf("%d", &message.fine);


        write(sock, &message, sizeof(struct Data));
        read(sock, &response, sizeof(struct Data));

        if(response.risultato == -1)
        {
            fprintf(stderr, "\nServer returned Writing Error\n");
            exit(EXIT_FAILURE);
        }
        else if(response.risultato == 1)
        {
            printf("\nSuccess in Operation\n");
        }
    }
    close(sock);
    exit(EXIT_SUCCESS);
}

这是服务器:

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <pthread.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

struct Data 
{
    int a;
    float b;
    int fine;
    int risultato;
};



void * handler(void * args)
{
    struct Data message;    
    int sock = *(int *)args;
    FILE *fp;

     if(!(fp = fopen("result.txt", "a")))
        {
        fprintf(stderr, "Error in opening file\n");
        exit(EXIT_FAILURE);
        }

    while(1)
    {

        read(sock, &message, sizeof(struct Data));

        printf("%d, %f, %d", message.a, message.b, message.fine);

        if(fprintf(fp,"\n[%d] [%.2f]\n", message.a, message.b) < 0)
        {
            message.risultato = -1;
        }
        else{
            message.risultato = 1;
        }

        if(message.fine == 1)
        {
            break;
        }
        write(sock, &message, sizeof(struct Data));

    }
    fclose(fp);
    close(sock);
    free(args);
    pthread_exit(NULL);
}


int main()
{
    int sock, client_sock;
    int * new_sock;

    pthread_t tid;

    struct sockaddr_in address, client_address;
    address.sin_family = AF_INET;
    address.sin_port = htons(6869);
    address.sin_addr.s_addr = inet_addr("127.0.0.1");

    socklen_t sock_len = (socklen_t)sizeof(address);


    sock = socket(AF_INET, SOCK_STREAM, 0);

    bind(sock, (struct sockaddr *)&address, sock_len);

    listen(sock, 3);

    while(1)
    {
       new_sock = (int *)malloc(sizeof(int));
       sock_len = sizeof(client_address);
       client_sock = accept(sock, (struct sockaddr *)&client_address, &sock_len); 
       *new_sock = client_sock;       
       pthread_create(&tid, NULL, handler, (void *)new_sock);
       pthread_detach(tid);
    }

}

实际结果应该是message.a和message.b中的数字顺序打印在文件上。

问题是每次创建文件时,它都会被数千个零填充,这表明读写函数无法正常工作

警告您使用SOCK_STREAM,您没有保证在一次读取时读取所有预期的字节。

在服务器中,您需要检查结果

   read(sock, &message, sizeof(struct Data));

在没有读取所有if的情况下中断错误或再次读取,否则当没有读取任何内容或者如果读取的内容少于预期大小时消息完全或部分未更改或未设置如果它是在第一个循环并且您有机会循环直到时间结束,当然您在文件中打印的值也保持不变或无效。

您可能遇到的情况是:在服务器中的交换(可能是第一个)期间, 读取不会读取所有结构,因为该message.fine未设置为1而其他一些值也未设置,因为message.fine != 1你再次循环,你再次读取但是从未读的字节而不是从结构的开头读取,所以即使你读取sizeof(Data)字节,结构没有很好地填充,并且message.fine再次没有设置为1而其他属性没有设置正确的值等,并且在某个时刻没有任何东西可以阅读,并且你无限循环,因为消息保持不变。

当然,我鼓励您也检查写入结果,当您在客户端阅读时遇到同样的问题

必须修改客户端/服务器端读取代码以检查读取调用的返回值。 请记住,当您使用SOCK_STREAM时,发送的所有数据都作为流(而不是数据报)发送和接收,从而导致后续发送的数据被放在一起,同样不需要接收单个发送的所有数据。一个人走到另一边。

修改了服务器的代码片段(只是一个伪代码),请检查并修改原始代码:

while(1)
{
    int res_bytes = 0;
    int res = 0;
    while (res_bytes < sizeof(struct Data))
    {
        res = read(sock, &message+res_bytes, (sizeof(struct Data) - res_bytes));
        if ((res == 0) || (res == -1))
        {
            printf("read returned an error, returning");
            return;
        }
        res_bytes = res_bytes + res;
    }

    printf("%d, %f, %d", message.a, message.b, message.fine);

    if(fprintf(fp,"\n[%d] [%.2f]\n", message.a, message.b) < 0)
    {
        message.risultato = -1;
    }
    else{
        message.risultato = 1;
    }

    if(message.fine == 1)
    {
        break;
    }
    res = write(sock, &message, sizeof(struct Data));
    if ((res == 0) || (res == -1))
    {
       printf("Error while writing");
       return;
    }
}

感谢@bruno和@Jay的帮助和所有建议。 我按如下方式安排了阅读部分:

do{

   res = read(sock, &message, sizeof(struct Data));

  }while(res < sizeof(struct Data));

写作同样的事情,现在它的作品!

PS我注意到如果我在fprintf成功后没有刷新文件流,则文件不会被打印,它会在循环中断后打印出来。 为什么会这样?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM