Please note that in HTTP, each line must be ended with “\r\n” (it’s not sufficient to use just “\n” or endl). • Don’t forget to include the “Connection: close” line in your client’s request. This tells the server that it shouldn’t wait around for your client to send any more requests after this one. Instead, the server will send one reply and then will immediately end its outgoing bytestream (the one from the server’s socket to your socket). You’ll discover that your incoming byte stream has ended because your socket will reach “EOF” (end of file) when you have read the entire byte stream coming from the server. That’s how your client will know that the server has finished its reply. • Make sure to read and print all the output from the server until the socket reaches “EOF” (end of file)—a single call to read is not enough. • We expect you’ll need to write about ten lines of code.
voidget_URL(const string &host, const string &path){ // Your code here.
// You will need to connect to the "http" service on // the computer whose name is in the "host" string, // then request the URL path given in the "path" string.
// Then you'll need to print out everything the server sends back, // (not just one call to read() -- everything) until you reach // the "eof" (end of file).
size_tByteStream::write(const string &data){ DUMMY_CODE(data); size_t can_write = min(data.size(), remaining_capacity()); for (size_t i = 0; i < can_write; ++i) { buffer_.push_back(data[i]); // push from the input side. } write_num_ += can_write; return can_write; }
//! \param[in] len bytes will be copied from the output side of the buffer string ByteStream::peek_output(constsize_t len)const{ DUMMY_CODE(len); size_t can_peek = min(len, buffer_.size()); string peek_data = ""; for (size_t i = 0; i < can_peek; ++i) { peek_data += buffer_[i]; } return peek_data; }
//! \param[in] len bytes will be removed from the output side of the buffer voidByteStream::pop_output(constsize_t len){ DUMMY_CODE(len); if (len > buffer_.size()) { set_error(); return; } for (size_t i = 0; i < len; ++i) { buffer_.pop_front(); // removed from the output side. } read_num_ += len; }
//! Read (i.e., copy and then pop) the next "len" bytes of the stream //! \param[in] len bytes will be popped and returned //! \returns a string std::string ByteStream::read(constsize_t len){ DUMMY_CODE(len); string message = ""; size_t can_read = min(len, buffer_.size()); // next "len" bytes. for (size_t i = 0; i < can_read; ++i) { message += buffer_.front(); buffer_.pop_front(); } read_num_ += can_read; return message; }
classByteStream { private: // Your code here -- add private members as necessary.
// Hint: This doesn't need to be a sophisticated data structure at // all, but if any of your tests are taking longer than a second, // that's a sign that you probably want to keep exploring // different approaches. std::deque<char> buffer_; size_t capacity_; // capacity in memory. bool end_write_; size_t read_num_; size_t write_num_;
bool _error{}; //!< Flag indicating that the stream suffered an error.