Ошибка передачи файла сокета C - PullRequest
1 голос
/ 02 августа 2011

У меня есть код передачи файла, написанный на C с использованием Windows-сокетов, который, кажется, работает, но продолжает передавать меньше, чем нужно, количество байтов файла.

Есть идеи?

Отправить код:

while(!feof(fp))
{
   bzero(bufferin,256);
   fread(bufferin,sizeof(char),255,fp);
   send(remsock,bufferin,255,0);

   if(n < 0)
      error("ERROR writing to socket");
}
send(remsock,"done",255,0);

Примите код:

while(1)
{
    recv(sockfd,buffer,255,0);
    if(compare(buffer,"done") == 0)
        break;  
    fwrite(buffer,1,255,fplog);
}
printf("File Transfer complete\n\n");

Ответы [ 4 ]

3 голосов
/ 02 августа 2011

Проблема в том, что send и recv работают не так, как вы ожидаете.

send(remsock,bufferin,255,0); /* Write MAX 255. May write less than 255. */
recv(sockfd,buffer,255,0); /* Read MAX 255. May read less than 255. */

Обычно проблема заключается в приемной стороне.Таким образом, вы должны прочитать в цикле.

while (bytes_to_go) {
    bytes = recv(...);
    /* Check bytes. */
    bytes_to_go -= bytes;
}
1 голос
/ 02 августа 2011

Как уже говорили другие, вы ДОЛЖНЫ посмотреть на возвращаемые значения всех функций, которые вы вызываете, например:

Отправка:

while (!feof(fp))
{
    int nRead = fread(bufferin, sizeof(char), 256, fp);
    if (nRead <= 0)
        error("ERROR reading file");

    char *pBuf = bufferin;
    while (nRead > 0)
    {
        int nSent = send(remsock, pBuf, nRead, 0);
        if (nSent == SOCKET_ERROR)
        {
            if (WSAGetLastError() != WSAEWOULDBLOCK)
                error("ERROR writing to socket");

            fd_set writefd;
            FD_ZERO(&writefd);
            FD_SET(remsock, &writefd);

            if (select(0, NULL, &writefd, NULL, NULL) != 1)
                error("ERROR waiting to write to socket");

            continue;
        }

        if (nSent == 0)
            error("DISCONNECTED writing to socket");

        pBuf += nSent;
        nRead -= nSent;
    }
}

closesocket(remsock);

Принимающий:

while(1)
{
    int nRecv = recv(sockfd, buffer, 256, 0);
    if (nRecv == SOCKET_ERROR)
    {
        if (WSAGetLastError() != WSAEWOULDBLOCK)
            error("ERROR reading from socket");

        fd_set readfd;
        FD_ZERO(&readfd);
        FD_SET(sockfd, &readfd);

        if (select(0, &readfd, NULL, NULL, NULL) != 1)
            error("ERROR waiting for data from socket");

        continue;
    }

    if (nRecv == 0)
        break;

    char *pBuf = buffer;
    while (nRecv > 0)
    {
        int nWritten = fwrite(pBuf, sizeof(char), nRecv, fplog);
        if (nWritten <= 0)
            error("ERROR writing to file");

        pBuf += nWritten;
        nRecv -= nWritten;
    }
}

printf("File Transfer complete\n\n"); 
0 голосов
/ 02 августа 2011

Похоже, что эта комбинация работает и дает правильную контрольную сумму для файлов.Важно использовать fclose () в конце, а также отправлять правильное количество байтов, захватывая возвращаемые значения, как сказали люди.Спасибо за ответы, хотя я немного обеспокоился, когда люди упомянули, что функции send и rcv отправляют максимум 255 в моем случае байтов и могут отправлять меньше.Я провел много испытаний и не заметил проблемы с передачей.

Отправьте код:

FILE *fp;
fp = fopen("c:\\file.txt", "rb");

while(!feof(fp))
{
   bzero(buffer,256);
   n = fread(buffer,sizeof(char),255,fp);
   send(remsock,buffer,n,0);

   if(n < 0)
      error("ERROR writing to socket");
}
send(remsock,"done",255,0);
fclose(fp);

Получите код:

FILE *fp;
fp = fopen("c:\\receivedfile.txt", "wb");

while(1)
{
    n = recv(sockfd,buffer,255,0);
    if(compare(buffer,"done") == 0)
        break;  
    fwrite(buffer,1,n,fp);
}
printf("File Transfer complete\n\n");
fclose(fp);
0 голосов
/ 02 августа 2011

Взгляните на sendfile() и recv() * MSG_WAITALL.

...