Question

I'm trying to PUT a binary JPEG file from client to server using sockets in C++. The JPEG file gets transferred fine most times. However, there are times where it gets transferred with a larger file size and the photo has pixelated sections. What could be the issue?

Here is my code on the server side that uses recv():

void FtpThread::CPut(std::vector<std::string>& Arguments)
{
    //filesize of file being put on server
    const int size = atoi(Arguments[2].c_str());

    char *memblock;
    memblock = new char[size];      
    //Sets memblock to 0's
    memset(memblock, 0, size);

    //send client a confirmation - 150 ok to send data
    send(s, Ftp::R150_PUT.c_str(), Ftp::R150_PUT.length(), 0);

    //stores the return value of recv()
    int r;

    char currentPath[FILENAME_MAX];
    std::string filePath;
    //gets the full path of the current working directory 
    _getcwd(currentPath, sizeof(currentPath) / sizeof(TCHAR));
    filePath = currentPath + std::string("\\") + FtpThread::FILE_DIRECTORY + std::string("\\") + Arguments[1];


    //open file (output file stream)
    std::ofstream file(filePath, std::ios::out|std::ios::binary|std::ios::trunc);

    if (file.is_open())
    {   
        //while memory blocks are still being received
        while ((r = recv(ds, memblock, FtpThread::BUFFERSIZE, 0)) != 0) 
        {
            //if there's a socket error, abort
            if (r == SOCKET_ERROR) 
            {
                std::cerr << "WSA Error Code:" << WSAGetLastError() << std::endl;
                //send client "Requested action aborted. Local error in processing."
                send(s, Ftp::R451.c_str(), Ftp::R451.length(), 0);
                file.close();
                closesocket(ds);
                return;
            }

            //write client's file blocks to file on server
            file.write(memblock, FtpThread::BUFFERSIZE);
        }

        closesocket(ds);

        delete[] memblock;

        //finished sending memory blocks; file is completely transferred.
        file.close();

        //let client know "226 File send OK"
        send(s, Ftp::R226_PUT.c_str(), Ftp::R226_PUT.length(), 0);
    } 
    else //if no such file exists on server - send a "550 Failed to open file"
    {
        send(s, Ftp::R550.c_str(), Ftp::R550.length(), 0);
    }
}

Here is my code on the client side that uses send():

std::ifstream::pos_type size;
        char* memblock;

        std::ifstream file(filename, std::ios::in|std::ios::binary|std::ios::ate);

        if (file.is_open())
        {
            size = file.tellg();

            if(size > 0)
            {
                memblock = new char[size];
                file.seekg(0, std::ios::beg);
                file.read(memblock, size);
                file.close();
                sendData(memblock, size);

                delete[] memblock;
            }

            closesocket(sockData);

            handleResponse();
        }
Was it helpful?

Solution

file.write(memblock, FtpThread::BUFFERSIZE);

should be

file.write(memblock, r);

You're assuming that recv() fills the buffer.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top