使用文件指针通过 TCP 传输文件的问题

发布于 2024-10-16 20:52:06 字数 3554 浏览 2 评论 0原文

我需要通过 TCP 传输 8.3MB 的文件,当我使用文件指针读取和写入文件时,我发送大约 8.6MB 数据,并且通过计算 send 和 recv 调用的输出接收 8.6MB 数据,尽管我的文件大小是 8.3 MB,此外,当我通过查看文件的属性单独检查文件的大小时,它大约是 3-5 MB(每次传输都有所不同),但是当我使用文件描述符代替文件指针时,我发送和接收的大小正好是 8.3数据 MB 和文件属性大小也显示为 8.3 MB。那么使用文件指针有什么问题以及为什么在文件描述符的情况下它被删除......但是如果我使用文件描述符那么我无法读取我发送的文本文件。文本编辑器显示文件中的一些二进制数据。我不知道发生了什么...请帮助并提前感谢

server.cpp

#include "server.h"
void server()
{
    int fd = open("out.txt",O_WRONLY);
    struct sockaddr_in sin;
    socklen_t addr_size;
    char buf[MAX_LINE];
    int len;
    int s, new_s;
    /* build address data structure */
    bzero((char *) & sin, sizeof (sin));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = INADDR_ANY;
    sin.sin_port = htons(SERVER_PORT);
    printf("File Descriptor : %d", fd);
    /* setup passive open */
    if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("simplex-talk: socket");
        exit(1);
    }
    if ((bind(s, (struct sockaddr *) & sin, sizeof (sin))) < 0)
    {
        perror("simplex-talk: bind");
        exit(1);
    }
    listen(s, MAX_PENDING);
    // wait for connection, then receive and print text */
    while (1) 
    {
        if ((new_s = accept(s, (struct sockaddr *) & sin, &addr_size)) < 0)
        {
            perror("simplex-talk: accept");
            exit(1);
        }
        float total = 0;
        printf("File Descriptor : %d", fd);
        while (len = recv(new_s, buf, MAX_LINE, 0) && strcmp(buf,"close"))
        {
            buf[len] = 0;
            total = total+len;
            //write(stdout, buf, len);
            write(fd, buf, len);
            //printf("%fKB and %fMB\n",total/1024, total/(1024*1024));
        }
        printf("File Descriptor : %d", fd);
        close(new_s);
    }
}

client.cpp

#include "client.h"
void client(int argc, char** argv)
{
    int fd = open("/home/nikku/Desktop/data.txt",O_RDONLY);
    if (fd < 0 ) perror("File not opened\n");
    struct hostent *hp;
    struct sockaddr_in sin;
    char *host;
    char buf[MAX_LINE];
    int s;
    int len;
    host = argv[1];
    if (argc == 2)
    {
        host = argv[1];
    }
    else
    {
        fprintf(stderr, "usage: simplex-talk host\n");
        exit(1);
    }
    /* translate host name into peer’s IP address */
    gethostname(host,20);
    printf("%s\n",host);
    hp = gethostbyname(host);
    if (!hp)
    {
        fprintf(stderr, "simplex-talk: unknown host: %s\n", host);
        exit(1);
    }
    /* build address data structure */
    bzero((char *) & sin, sizeof (sin));
    sin.sin_family = AF_INET;
    bcopy(hp->h_addr, (char *) & sin.sin_addr, hp->h_length);
    sin.sin_port = htons(SERVER_PORT);
    /* active open */
    if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("simplex-talk: socket");
        exit(1);
    }
    if (connect(s, (struct sockaddr *) & sin, sizeof (sin)) < 0)
    {
        perror("simplex-talk: connect");
        close(s);
        exit(1);
    }
    printf("Connection Succeeded\n");
    /* main loop: get and send lines of text */
    float total = 0;
    while (read(fd, buf, MAX_LINE))
    {
        //usleep(1000);;
        len = strlen(buf) + 1;
        total += send(s, buf, len, 0);
        //printf("%fKB and %fMB\n",total/1024, total/(1024*1024));
    }
    send(s, "close", 6, 0);
    close(fd);
}

只是如果我用指针替换文件描述符的使用并使用 fgets 和 fputs 来读取和写入,那么我的文件传输不会正确服用。但是如果我使用文件描述符,那么我将无法读取我发送的文本文件。文本编辑器显示文件中的一些二进制数据。

i need to transfer a file of 8.3MB over TCP, when i use file pointers to read and write to files then i send about 8.6MB data and also receives 8.6 MB of data by calculating the output of send and recv calls although my file size is 8.3 MB, further the when i check the size of file separately by seeing its properties then it is around 3-5 MB (varies on every transfer) but when i use file descriptors in place of file pointers then i send and recv exactly 8.3 MB of data and file property size also shows 8.3 MB. So what is the problem in using file pointers and why is it removed in case of file descriptors.... but if i use file descriptors then i am not able to read the text file that i sent. Text editors shows some binary data in the file. i am not getting a bit of what is happening... please help and thanks in advance

server.cpp

#include "server.h"
void server()
{
    int fd = open("out.txt",O_WRONLY);
    struct sockaddr_in sin;
    socklen_t addr_size;
    char buf[MAX_LINE];
    int len;
    int s, new_s;
    /* build address data structure */
    bzero((char *) & sin, sizeof (sin));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = INADDR_ANY;
    sin.sin_port = htons(SERVER_PORT);
    printf("File Descriptor : %d", fd);
    /* setup passive open */
    if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("simplex-talk: socket");
        exit(1);
    }
    if ((bind(s, (struct sockaddr *) & sin, sizeof (sin))) < 0)
    {
        perror("simplex-talk: bind");
        exit(1);
    }
    listen(s, MAX_PENDING);
    // wait for connection, then receive and print text */
    while (1) 
    {
        if ((new_s = accept(s, (struct sockaddr *) & sin, &addr_size)) < 0)
        {
            perror("simplex-talk: accept");
            exit(1);
        }
        float total = 0;
        printf("File Descriptor : %d", fd);
        while (len = recv(new_s, buf, MAX_LINE, 0) && strcmp(buf,"close"))
        {
            buf[len] = 0;
            total = total+len;
            //write(stdout, buf, len);
            write(fd, buf, len);
            //printf("%fKB and %fMB\n",total/1024, total/(1024*1024));
        }
        printf("File Descriptor : %d", fd);
        close(new_s);
    }
}

client.cpp

#include "client.h"
void client(int argc, char** argv)
{
    int fd = open("/home/nikku/Desktop/data.txt",O_RDONLY);
    if (fd < 0 ) perror("File not opened\n");
    struct hostent *hp;
    struct sockaddr_in sin;
    char *host;
    char buf[MAX_LINE];
    int s;
    int len;
    host = argv[1];
    if (argc == 2)
    {
        host = argv[1];
    }
    else
    {
        fprintf(stderr, "usage: simplex-talk host\n");
        exit(1);
    }
    /* translate host name into peer’s IP address */
    gethostname(host,20);
    printf("%s\n",host);
    hp = gethostbyname(host);
    if (!hp)
    {
        fprintf(stderr, "simplex-talk: unknown host: %s\n", host);
        exit(1);
    }
    /* build address data structure */
    bzero((char *) & sin, sizeof (sin));
    sin.sin_family = AF_INET;
    bcopy(hp->h_addr, (char *) & sin.sin_addr, hp->h_length);
    sin.sin_port = htons(SERVER_PORT);
    /* active open */
    if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("simplex-talk: socket");
        exit(1);
    }
    if (connect(s, (struct sockaddr *) & sin, sizeof (sin)) < 0)
    {
        perror("simplex-talk: connect");
        close(s);
        exit(1);
    }
    printf("Connection Succeeded\n");
    /* main loop: get and send lines of text */
    float total = 0;
    while (read(fd, buf, MAX_LINE))
    {
        //usleep(1000);;
        len = strlen(buf) + 1;
        total += send(s, buf, len, 0);
        //printf("%fKB and %fMB\n",total/1024, total/(1024*1024));
    }
    send(s, "close", 6, 0);
    close(fd);
}

Just if i replace use of file descriptors with pointers and use fgets and fputs to read and write then my file transfer does not take properly. But if i use file descriptors then i am not able to read the text file that i sent. Text editors shows some binary data in the file.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

你曾走过我的故事 2024-10-23 20:52:06
while (read(fd, buf, MAX_LINE))
{
    //usleep(1000);;
    len = strlen(buf) + 1;
    total += send(s, buf, len, 0);
    //printf("%fKB and %fMB\n",total/1024, total/(1024*1024));
}

这里有一个问题,您无法保证 read 会读取零字节,因此 strlen(buf) 存在潜在危险。另请注意,当您将 len 设置为 strlen(buf) + 1 时,如果您确实遇到零字节,您将通过套接字发送它,但如果您不这样做读取零字节,strlen 将读取超出数组末尾的内容并通过套接字发送“垃圾”。

明智的做法是存储 read 的返回值,以便您知道实际从 fd 读取了多少字节。

while (len = recv(new_s, buf, MAX_LINE, 0) && strcmp(buf,"close"))
{
    buf[len] = 0;
    total = total+len;
    //write(stdout, buf, len);
    write(fd, buf, len);
    //printf("%fKB and %fMB\n",total/1024, total/(1024*1024));
}

您的接收端似乎假设每次对 recv 的调用都不会包含零字节,因为您手动用 0 终止缓冲区。请注意,如果 recv 实际上,您实际上没有空间执行此操作接收 MAX_LINE 字节,因为 buf 仅由 MAX_LINE 元素组成。由于您的写入在任何情况下都受到长度限制,因此无需执行 buf[len] = 0;

while (read(fd, buf, MAX_LINE))
{
    //usleep(1000);;
    len = strlen(buf) + 1;
    total += send(s, buf, len, 0);
    //printf("%fKB and %fMB\n",total/1024, total/(1024*1024));
}

There is an issue here, you have no guarantee that read will read a zero byte so strlen(buf) is potentially dangerous. Also note, that as you set len to strlen(buf) + 1, if you do encouter a zero byte you will send it across the socket but if you don't read a zero byte, strlen will read beyond the end of the array and send 'junk' across the socket.

It would be sensible to store the return value of read so that you know how many bytes were actually read from fd.

while (len = recv(new_s, buf, MAX_LINE, 0) && strcmp(buf,"close"))
{
    buf[len] = 0;
    total = total+len;
    //write(stdout, buf, len);
    write(fd, buf, len);
    //printf("%fKB and %fMB\n",total/1024, total/(1024*1024));
}

Your receive side seems to assume that each call to recv won't include a zero byte as you manually terminate the buffer with a 0. Note that you don't actually have room to do this if recv actually receives MAX_LINE bytes as buf only consists of MAX_LINE elements. As your write is restricted by length in any case, there is no need to do buf[len] = 0;.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文