Hi everyone. I’m gonna demonstrate how to do proper file uploading and downloading via TCP sockets. I’m going to be using Windows Sockets API (winsock) in this. But the following can be done on linux sockets too.

Why This?

Well, A lot of new socket programmers have a hard time sending and receiving files in C/C++. And I myself had a hard time figuring out. After many really bad implementations. The one I’m going to show you today, Is the one that is so far the best one.

I’m going to skip over basic socket operations such as creating socket, connecting to server and all. Let’s start with a simple receive loop.

char recvbuf[1024] = {0};
while(connected){
    int data = recv(socket, recvbuf, 1024, 0);
    // add error handling for data
    if(strcmp(recvbuf, "Savethisfile") == 0)
    {
        // Lets save the file.
    }

}

The above snippet expects, That the socket socket is connected. And we are receving data in a while loop. If the received data is “Savethisfile”, Then we receive the file. So lets do that now.

I’m also going to skip another step here. Which is sending the file name To save the file into. You can easily do that by sending the file name after, Or sending something like Savethisfile=lol.exe and the client parses it to save the file lol.exe.

Over here, I’ll receive in demo.txt.

char recvbuf[1024] = {0};
while(connected){
    int data = recv(socket, recvbuf, 1024, 0);
    // add error handling for data
    if(strcmp(recvbuf, "Savethisfile") == 0)
    {
        HANDLE saveFile = CreateFile("demo.txt", FILE_APPEND_DATA, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
        if(saveFile != INVALID_HANDLE_VALUE)
        {
            memset(recvbuf, '\0', BUFFER); // Clear main buffer
                int total = 0; // Total bytes received

                do { // IF Total is equal to expected bytes. Break the loop, And stop receiving.
                    int fsize = recv(sockfd, recvbuf, BUFFER, 0); // Receive file
                    if (fsize == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET)
                    {
                        connected = FALSE;
                        // Connection error
                    }
                    else if (fsize == 0) {
                        break;
                    }
                    else {
                        write = WriteFile(recvfile, recvbuf, fsize, &dwBytesWritten, NULL); // Write file data to file
                        total += fsize; // Add number of bytes received to total.
                    }
                } while (total != expected);

                if (write == FALSE)
                {
                    // Error writing file
                }
                else {
                    // We got the file!
                }
                CloseHandle(recvfile); // close file handle
        }
    }

}

This receives the file in chunks, And those chunks are written to the file. This will work on overlapped / non overlapped socket.
Now for the uploading part.

if ((fs = fopen("send.txt", "rb")) != NULL)
                    {
                        fseek(fs, 0L, SEEK_END);
                        long filesize = ftell(fs);
                        fseek(fs, 0, SEEK_SET);

                        if(filesize <= 0){
                           // File is of 0 bytes
                            fclose(fs);
                            upload = FALSE;
                            break;
                        }

                        send(sockfd, "SavethisFile", sizeof("SavethisFile"),0);
                        Sleep(1000);
                        char fbuffer[500];
                        memset(fbuffer, '\0', 500);
                        while (!feof(fs)) {
                            if ((bytes_read = fread(&fbuffer, 1, 500, fs)) > 0) {
                                send(sockfd, fbuffer, bytes_read, 0);
                            }
                            else {
                                upload = FALSE;
                                break;
                            }
                        }
                        fclose(fs);
                    }

That code is a working prototype for socket file transfer. If you much improve it and tune it to your needs, It will look something like this.

Categories: Uncategorized

0 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *