I’ve completed our second assignment of the course, the C++ web server.
After having completed the required tasks for the assignment I challenged myself by trying to send images with the server as well. It seems easy, you need to load the image into memory and send it as usual with a HTTP-header. Well, it wasn’t as easy as that for me, I needed to make some major changes to my previous code.
The first step, loading the image into memory. I had never loaded an image using std::fstream before but I started by trying to read it like any other file. Previously, I had only used streaming from a file with regular streaming “<<” and “getline()”. Neither of these worked because images are often filled with characters equals to “\ 0” and when that sign occurs when streaming (“<<“) or getline-ing operations are stopped. It’s the standard character for the end of the file when using std::string and std::fstream.
I tried to find a solution and finally I did. When opening the file I set the ios mode to binary and used the fstream function read(). When sending the message to clients I need to supply the size of it, for that I used the fstream function gcount(), it correctly returns the size of the file.
The reason for using a pointer to the heap for the buffer is to support sending bigger images. If trying to allocate memory in the stack when there is no space for it, programs crash and the total size of the stack memory is very limited.
The next step was sending the image with a header. My method for sending messages was using a std::stringstream at the time and converting the buffer to a std::string or streamstream is harder than it seems. When encountering the first “\ 0”-character it would stop the conversion. I actually made a work-around to get this to work. I made a new buffer in the send-method and for-looped in the header, then the message.
It’s not pretty but it works like a charm! This was the result:
To explain my send-method: It takes a target socket, a message, a message length and header information. Another method (the asString_Header()) takes care of converting the header information into a std::string. Thereafter the header is inserted into the buffer, and then the message is inserted after it. This method works for both text and images.
I’d also like to adress the fact that I allocate buffers in the heap of over 10 megabytes (the current value of the #define MAX_SEND) each time I send a message regardless of their size. The information sent to remote sockets are only the exact size of the messages/images themselves though. Anyways, the point I want to make is that this way of doing it is probably not optimal.
I’ve learned a lot by doing this and that was the point of doing it, so mission successful! :)