【问题标题】:Sending and receiving a file - sockets - c - windows发送和接收文件-sockets-c-windows
【发布时间】:2014-09-30 14:59:00
【问题描述】:

我尝试在网上查找大量页面,发现没有适合 Windows 并且始终有效,我通过 TCP 协议尝试了这个(逐字节流式传输,直到遇到 3 - 我试过了里面没有 3 的文件:PPPP 和 3 我的意思是 ASCII 值 3 而不是数字 '3')。

服务器端:

int sendFile(SOCKET s, const char* file_path)
{
    FILE* fp = fopen(file_path, "rb");
    int i, err = 0, bytesSent, isOk = 1;
    char ch = 0;
    if(!fp)
    {
        fclose(fp);
        return 1;
    }
    while(ch != EOF && isOk)
    {
        fread(&ch, sizeof(char), 1, fp);
        if(ch != EOF)
        {
            bytesSent = send(s, &ch, sizeof(char), 0);
            if(bytesSent <= 0)
            {
                 return 1;
            }
        }
        else
        {
            isOk = 0;
        }
    }
    ch = 3;
    bytesSent = send(s, &ch, sizeof(char), 0);

    fclose(fp);

    return 0;
}

客户端:

int recvFile(SOCKET s, const char* file_path)
{
    FILE* fp = fopen(file_path, "wb");
    int bytesRecieved;
    char ch;
    if(!fp)
    {
        fclose(fp);
        return 1;
    }
    bytesRecieved = recv(s, &ch, sizeof(char), 0);
    if(bytesRecieved <= 0)
    {
         return 1;
    }
    while(ch != 3)
    {
        fwrite(&ch, sizeof(char), 1, fp);
        putch(ch);
        bytesRecieved = recv(s, &ch, sizeof(char), 0);
        if(bytesRecieved <= 0)
        {
            return 1;
        }
    }

    fclose(fp);

    return 0;
}

套接字运行良好,发送和接收良好(我说的是发送常规消息,没有这些功能)。 它没有返回 1,它只是变成了一个无限循环。 不知道为什么它不起作用,知道吗?我完全绝望了。

【问题讨论】:

  • 我会先把 while(ch != 3) 改成 while(bytesReceived > 0 && ch != 3)
  • @ServéLaurijssen 我添加了另一种方式:P
  • 用EOF比较一个字符是错误的(查一下),需要检查fread()的返回值

标签: c windows file sockets


【解决方案1】:

在读取文件时,您应该使用feof 函数,而不是与 EOF 进行比较。 EOF 只是某些函数返回的错误代码,而不是文件中的实际字符。

另外,我注意到带有字符 3 的东西似乎是一种表示文件结束的方式。您应该考虑规范化数据传输。您可以在通信开始时发送文件的大小,客户端会准确读取文件的大小,以避免包含该字符的文件出现问题(3 仍然是有效字符)。

为了获得灵感,请查看我的 old project,它实现了这种行为(尽管它仅适用于 linux)。

【讨论】:

  • 对了,我应该如何发送长度?当然,我可以使用 itoa() 将其转换为字符串,但发送 4 个字节的 int 而不是使用 void* 将其视为 int* 不是更好吗?
【解决方案2】:

我曾经在 tcp 套接字上读取比用于写入的块更小的块时遇到了麻烦。在套接字上,您写入确定长度的数据包(写入或发送),如果读取大小较短,实现可能会丢弃数据包的末尾。

来自 recv 的手册页:所有三个例程 [recv, recvfrom, recvmsg] 在成功完成时返回消息的长度。如果消息太长而无法放入提供的缓冲区,则可能会丢弃多余的字节,具体取决于接收消息的套接字类型。

阅读时,您应该始终使用大小至少等于写入时使用的最长缓冲区大小的缓冲区。

您可以转储收到的内容以确认。

【讨论】:

  • 我使用一个字符的缓冲区发送并使用一个字符接收...:P
猜你喜欢
  • 2019-07-10
  • 2015-11-12
  • 1970-01-01
  • 2011-08-06
  • 2021-09-07
  • 2012-08-10
  • 2018-05-03
  • 1970-01-01
  • 2020-06-08
相关资源
最近更新 更多