【问题标题】:Reading a file from a specific point problem从特定点问题读取文件
【发布时间】:2019-05-21 11:31:16
【问题描述】:

我正在使用 TCP 服务器/客户端 C 应用程序将文件从服务器发送到客户端。文件必须分部分发送(一个连接一个部分)。我成功地将文件从服务器发送到客户端,这不是问题。问题在于每个连接的一个部分,要发送正确的部分。我正在使用 fseek() 来查找整个文件的大小并将其除以 4。这就是我想要发送给客户端的块的大小。问题仍然存在,因为我得到的块比我实际预期的要多。

// Retrieve file size
fSize = fileSize(filePtr);

// How much bytes to send
if (fSize >= 4)
{
    leftToSend = fSize / SEND_DENOM;
}
else
{
    leftToSend = fSize;
}

int fpOffset = leftToSend * (partToSend - 1);

fseek(filePtr, fpOffset, SEEK_SET);

int i = 0;
char cFromFile;

while(leftToSend != 0 || feof(filePtr))
{

    cFromFile = fgetc(filePtr);
    dataBuffer[i++] = cFromFile;

    leftToSend--;
    bytesSent++;

    if (strlen(dataBuffer) == (BUFFER_SIZE - 1) || leftToSend == 0)
    {
        // Send message to client
        iResult = sendto(clientSocket,                      
                            dataBuffer,                     
                            strlen(dataBuffer),             
                            0,                              
                            (SOCKADDR *)&clientAddress,     
                            sizeof(clientAddress)); 

        if (iResult == SOCKET_ERROR)
        {
            printf("sendto failed with error: %d\n", WSAGetLastError());
            closesocket(clientSocket);
            WSACleanup();
            ExitThread(100);
        }

        // Set whole buffer to zero
        memset(dataBuffer, 0, BUFFER_SIZE);

        i = 0;
    }

}

查找文件大小功能:

unsigned long long int fileSize (FILE* filePtr)
{
    unsigned long long int fSize = 0;

    fseek(filePtr, 0, SEEK_END);
    fSize = ftell(filePtr);
    rewind(filePtr);

    return fSize;
}

示例(它的外观):

这是个问题……

  1. 块 - 这个_

  2. 块 - is_a_

  3. 块 - 问题

  4. 块 - em...

这是我得到的:

  1. 块 - This_is_a

  2. 块 - is_a_prob

  3. 块 - 问题..

  4. 块 - em...

其中_代表空格

【问题讨论】:

  • 到目前为止,我无法从快速疏忽中识别出任何明显的警报。请发布 sendto 函数或至少解释它的作用。
  • 您没有将字符串终止符写入dataBuffer[ ],因此strlen 将失败。还有|| feof(filePtr) 是干什么用的?如果您已经有读取错误,为什么还要永远阅读?您知道文件的大小,因此只需计算字节数。
  • @WeatherVane 我假设作者将缓冲区初始化为零。 if 中还有一个 memset 为零
  • @john 好的,那么结束条件是strlen(dataBuffer) == (BUFFER_SIZE - 1),而不是块大小。 leftToSend 未重置。
  • 另外,我对块大小有点不清楚。您想一次发送 4 个字节吗?还是根据您的正确示例 5 个字节?还是 BUFFER_SIZE?

标签: c tcp tcpclient tcpserver


【解决方案1】:

从您提到的 cmets 中,尝试以下代码。 我假设您正确计算 leftToSend 变量。

while((leftToSend >= 0) || feof(filePtr))
{
    cFromFile = fgetc(filePtr);
    dataBuffer[i] = cFromFile;

    i++;
    leftToSend--;

    if ((i >= (BUFFER_SIZE - 1)) || (0 == leftToSend) || (i >= (SEND_DENOM + 1)))
    {
        // Send message to client
        iResult = sendto(clientSocket,                      
                         dataBuffer,                     
                         i,             
                         0,                              
                         (SOCKADDR *)&clientAddress,     
                         sizeof(clientAddress)); 

        if (SOCKET_ERROR == iResult)
        {
            printf("sendto failed with error: %d\n", WSAGetLastError());
            closesocket(clientSocket);
            WSACleanup();
            ExitThread(100);
        }

        // Set whole buffer to zero
        memset(dataBuffer, 0, BUFFER_SIZE);

        bytesSent += i;
        i = 0;
    }
}

【讨论】:

  • 感谢您的宝贵时间和帮助。添加 if(cFromFile == '\n') leftToSend--;在获得 cFromFile 的值后到 while 循环的主体解决了我的问题。显然我在用 win32 表示新行时遇到了一些问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多