-2

I am trying to upload files to the server, but they always come corrupted, the program is very simple, only serves to transfer files between client and server. I need assistance in this code, for fix the problem. and improve it.

SERVER

    int Socket_Manip::FILE_UPLOAD() {

    //get file size.
    iResult = recv(ClientSocket, GotFileSize, LENGTH, 0);
    if (iResult == 0)
    {
        closesocket(ClientSocket);
        WSACleanup();
        return 1;
    }
    else if (iResult < 0) {
        closesocket(ClientSocket);
        WSACleanup();
        return 1;
    }

    //start manip download
    long FileSize = atoi(GotFileSize);
    long SizeCheck = 0;
    char* mfcc;

    FILE *fp = fopen("C::\\Users\\Server\\Downloads\\transfer.zip", "wb");
    if (fp == NULL)
    {
        closesocket(ClientSocket);
        WSACleanup();
        return 1;
    }
    if (FileSize > 1499) {
        mfcc = (char*)malloc(1500);
        while (FileSize > SizeCheck){
            int Received = recv(ClientSocket, mfcc, 1500, 0);
            if (Received == 0)
            {
                break;
            }
            else if (Received < 0) {
                closesocket(ClientSocket);
                WSACleanup();
                return 1;
            }
            SizeCheck += Received;
            fwrite(mfcc, 1, Received, fp);
            fflush(fp);
        }
    } else 
    {
        mfcc = (char*)malloc(FileSize + 1);
        int Received = recv(ClientSocket, mfcc, FileSize, 0);
        fwrite(mfcc, 1, Received, fp);
        fflush(fp);
    }

    fclose(fp);
    free(mfcc);

}

CLIENT SENDER

int File_Transfer_Manip() {
    FILE *File;
    char *Buffer;
    unsigned long Size;


    File = fopen("C:\\Users\\r4minux\\Downloads\\upload.zip", "rb");
    if (!File)
    {
        printf("Error file\n");
        return 1;
    }

    fseek(File, 0, SEEK_END);
    Size = ftell(File);
    fseek(File, 0, SEEK_SET);

    Buffer = new char[Size];

    fread(Buffer, Size, 1, File);
    char cSize[MAX_PATH];
    sprintf(cSize, "%i", Size);

    fclose(File);
    iResult = send(ConnectSocket, cSize, MAX_PATH, 0); // File size
    if (iResult == SOCKET_ERROR) {
        printf("send erroR: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        getchar();
        return 1;
    }

    int Offset = 0;
    while (Offset < Size)
    {
        int Amount = send(ConnectSocket, Buffer + Offset, Size - Offset, 0);
        if (Amount <= 0)
        {
            std::cout << "Error: " << WSAGetLastError() << std::endl;
            break;
        }
        else
        {
            Offset += Amount;
        }
    }

    // cleanup
    free(Buffer);

}
Mrdk
  • 413
  • 1
  • 4
  • 10

1 Answers1

2

TCP is a byte stream. It has no concept of message boundaries. You are not making sure that send() is actually sending everything you give it, or that recv() is reading everything you ask it to. They CAN return fewer bytes. You have to account for that.

Try this instead:

SERVER:

int readBytes(SOCKET s, void *buffer, int buflen)
{
    int total = 0;

    char *pbuf = (char*) buffer;
    while (buflen > 0)
    {
        int iResult = recv(s, pbuf, buflen, 0);
        if (iResult < 0)
        {
            if (WSAGetLastError() == WSAEWOULDBLOCK)
            {
                // optionally use select() to wait for the
                // socket to have more bytes to read before
                // calling recv() again...
                continue;
            }

            printf("recv error: %d\n", WSAGetLastError());
            return SOCKET_ERROR;
        }
        else if (iResult == 0)
        {
            printf("disconnected\n");
            return 0;
        }
        else
        {
            pbuf += iResult;
            buflen -= iResult;
            total += iResult;
        }
    }

    return total;
}

int Socket_Manip::FILE_UPLOAD()
{
    //start download

    FILE *fp = fopen("C::\\Users\\Server\\Downloads\\transfer.zip", "wb");
    if (fp == NULL)
    {
        printf("Error creating file\n");
        closesocket(ClientSocket);
        WSACleanup();
        return 1;
    }

    //get file size.
    unsigned long FileSize;
    int iResult = readBytes(ClientSocket, &FileSize, sizeof(FileSize));
    if (iResult <= 0)
    {
        fclose(fp);
        closesocket(ClientSocket);
        WSACleanup();
        return 1;
    }
    FileSize = ntohl(FileSize);

    char mfcc[1024];
    while (FileSize > 0)
    {
        int Received = readBytes(ClientSocket, mfcc, min(sizeof(mfcc), FileSize));
        if (Received <= 0)
        {
            fclose(fp);
            closesocket(ClientSocket);
            WSACleanup();
            return 1;
        }

        if (fwrite(mfcc, 1, Received, fp) != Received)
        {
            printf("Error writing file\n");
            fclose(fp);
            closesocket(ClientSocket);
            WSACleanup();
            return 1;
        }

        FileSize -= Received;
    }

    fflush(fp);
    fclose(fp);

    return 0;
}

CLIENT

int sendBytes(SOCKET s, void *buffer, int buflen)
{
    int total = 0;

    char *pbuf = (char*) buffer;
    while (buflen > 0)
    {
        int iResult = send(s, pbuf, buflen, 0);
        if (iResult < 0)
        {
            if (WSAGetLastError() == WSAEWOULDBLOCK)
            {
                // optionally use select() to wait for the
                // socket to have more space to write before
                // calling send() again...
                continue;
            }

            printf("send error: %d\n", WSAGetLastError());
            return SOCKET_ERROR;
        }
        else if (iResult == 0)
        {
            printf("disconnected\n");
            return 0;
        }
        else
        {
            pbuf += iResult;
            buflen -= iResult;
            total += iResult;
        }
    }

    return total;
}

int File_Transfer_Manip()
{
    char Buffer[1024];

    FILE *fp = fopen("C:\\Users\\r4minux\\Downloads\\upload.zip", "rb");
    if (!fp)
    {
        printf("Error opening file\n");
        return 1;
    }

    fseek(fp, 0, SEEK_END);
    unsigned long FileSize = ftell(fp);
    fseek(fp, 0, SEEK_SET);

    unsigned long tmpFileSize = htonl(FileSize);
    int iResult = sendBytes(ConnectSocket, &tmpFileSize, sizeof(tmpFileSize));
    if (iResult <= 0)
    {
        fclose(fp);
        closesocket(ConnectSocket);
        WSACleanup();
        getchar();
        return 1;
    }

    while (FileSize > 0)
    {
        long Size = fread(Buffer, 1, min(sizeof(Buffer), FileSize), fp);
        if (Size <= 0)
        {
            printf("Error reading file\n");
            fclose(fp);
            closesocket(ConnectSocket);
            WSACleanup();
            getchar();
            return 1;
        }

        if (sendBytes(ConnectSocket, Buffer, Size) != Size)
        {
            fclose(fp);
            closesocket(ConnectSocket);
            WSACleanup();
            getchar();
            return 1;
        }

        FileSize -= Size;
    }

    fclose(fp);
    return 0;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • I adapted this code into a simple client/server, and it copies all except the first 4 bytes of the file from the client to the server. Noteably, when the server receives the size of the file in line `int iResult = readBytes(ClientSocket, &FileSize, sizeof(FileSize));`, it's 4 bytes. @RemyLebbeau – JeffR Jul 09 '22 at 17:33
  • Then you likely didn't adapt the code correctly. The client sends the file size as 4 bytes, then sends the file data. The server reads the file size as 4 bytes, then reads the file data. Everything is balanced. If that is not working for you, then you did something wrong. – Remy Lebeau Jul 09 '22 at 17:45
  • I just saw your other question on this issue, so I will review it and let you know what I find. – Remy Lebeau Jul 09 '22 at 18:01
  • Ok thank you very much. The line `int iResult = send(s, pbuf, buflen, 0);` won't work unless `pbuf` is casted to this: `int iResult = send(s, (char *) pbuf, buflen, 0);`, since `send` is expecting a `(char *)` and won't take this cast: `(unsigned char *)` – JeffR Jul 09 '22 at 18:16
  • 1
    I just posted on answer on your other question. Please stop commenting on this question now. – Remy Lebeau Jul 09 '22 at 18:18