rain0832@ubuntu:~$ telnet cs144.keithw.org http
Trying 198.18.0.99...
Connected to cs144.keithw.org.
Escape character is '^]'.
GET /hello HTTP/1.1
Host: cs144.keithw.org
Connection: close
HTTP/1.1 200 OK
Date: Mon, 24 Feb 2025 12:50:09 GMT
Server: Apache
Last-Modified: Thu, 13 Dec 2018 15:45:29 GMT
ETag: "e-57ce93446cb64"
Accept-Ranges: bytes
Content-Length: 14
Connection: close
Content-Type: text/plain
Hello, CS144!
Connection closed by foreign host.
rain0832@ubuntu:~$ telnet cs144.keithw.org http
Trying 198.18.0.99...
Connected to cs144.keithw.org.
Escape character is '^]'.
GET /lab0/test HTTP/1.1
Host: cs144.keithw.org
Connection: close
HTTP/1.1 200 OK
Date: Mon, 24 Feb 2025 13:06:10 GMT
Server: Apache
X-You-Said-Your-SunetID-Was: test
X-Your-Code-Is: 590984
Content-length: 108
Vary: Accept-Encoding
Connection: close
Content-Type: text/plain
Hello! You told us that your SUNet ID was "test". Please see the HTTP headers (above) for your secret code.
Connection closed by foreign host.
rain0832@ubuntu:~$ netcat -v -l -p 9090
Listening on 0.0.0.0 9090
rain0832@ubuntu:~$ telnet localhost 9090
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
rain0832@ubuntu:~/CS144/minnow$ cmake -S . -B build
-- The CXX compiler identification is GNU 11.4.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Setting build type to 'Debug'
-- Building in 'Debug' mode.
-- Configuring done (0.6s)
-- Generating done (0.2s)
-- Build files have been written to: /home/rain0832/CS144/minnow/build
rain0832@ubuntu:~/CS144/minnow$ cmake --build build
[ 10%] Building CXX object src/CMakeFiles/minnow_debug.dir/byte_stream.cc.o
[ 10%] Building CXX object util/CMakeFiles/util_debug.dir/address.cc.o
[ 15%] Building CXX object src/CMakeFiles/minnow_debug.dir/byte_stream_helpers.cc.o
[ 21%] Linking CXX static library libminnow_debug.a
[ 21%] Built target minnow_debug
[ 26%] Building CXX object tests/CMakeFiles/minnow_testing_debug.dir/common.cc.o
[ 31%] Building CXX object util/CMakeFiles/util_debug.dir/debug.cc.o
In file included from /home/rain0832/CS144/minnow/tests/common.hh:4,
from /home/rain0832/CS144/minnow/tests/common.cc:1:
/home/rain0832/CS144/minnow/util/debug.hh:3:10: fatal error: format: No such file or directory
3 | #include <format>
| ^~~~~~~~
compilation terminated.
make[2]: *** [tests/CMakeFiles/minnow_testing_debug.dir/build.make:79: tests/CMakeFiles/minnow_testing_debug.dir/common.cc.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:2978: tests/CMakeFiles/minnow_testing_debug.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....
[ 36%] Building CXX object util/CMakeFiles/util_debug.dir/eventloop.cc.o
In file included from /home/rain0832/CS144/minnow/util/debug.cc:1:
/home/rain0832/CS144/minnow/util/debug.hh:3:10: fatal error: format: No such file or directory
3 | #include <format>
| ^~~~~~~~
compilation terminated.
make[2]: *** [util/CMakeFiles/util_debug.dir/build.make:93: util/CMakeFiles/util_debug.dir/debug.cc.o] Error 1
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [CMakeFiles/Makefile2:2786: util/CMakeFiles/util_debug.dir/all] Error 2
make: *** [Makefile:101: all] Error 2
rain0832@ubuntu:~/CS144/minnow$ cmake --build build
[ 15%] Built target minnow_debug
[ 21%] Building CXX object util/CMakeFiles/util_debug.dir/debug.cc.o
[ 26%] Building CXX object tests/CMakeFiles/minnow_testing_debug.dir/common.cc.o
[ 31%] Building CXX object util/CMakeFiles/util_debug.dir/eventloop.cc.o
[ 36%] Linking CXX static library libminnow_testing_debug.a
[ 36%] Built target minnow_testing_debug
[ 42%] Building CXX object apps/CMakeFiles/stream_copy.dir/bidirectional_stream_copy.cc.o
[ 47%] Building CXX object util/CMakeFiles/util_debug.dir/file_descriptor.cc.o
[ 52%] Linking CXX static library libstream_copy.a
[ 52%] Built target stream_copy
[ 57%] Building CXX object util/CMakeFiles/util_debug.dir/helpers.cc.o
[ 63%] Building CXX object util/CMakeFiles/util_debug.dir/random.cc.o
[ 68%] Building CXX object util/CMakeFiles/util_debug.dir/socket.cc.o
[ 73%] Linking CXX static library libutil_debug.a
[ 78%] Built target util_debug
[ 84%] Building CXX object apps/CMakeFiles/webget.dir/webget.cc.o
[ 89%] Building CXX object apps/CMakeFiles/tcp_native.dir/tcp_native.cc.o
[ 94%] Linking CXX executable webget
[100%] Linking CXX executable tcp_native
[100%] Built target webget
[100%] Built target tcp_native
#include "socket.hh"
#include <cstdlib>
#include <iostream>
#include <span>
#include <string>
using namespace std;
void get_URL(const string& host, const string& path) {
// create TCP socket
TCPSocket socket;
// parse the address and connect
Address server_address(host, "http");
socket.connect(server_address);
// create HTTP request
string request = "GET " + path + " HTTP/1.1\r\n";
request += "Host: " + host + "\r\n";
request += "Connection: close\r\n\r\n";
// send the request
socket.write(request);
// read the response
string response;
string buffer; // 用于存储每次读取的数据
while (!socket.eof()) {
socket.read(buffer); // 读取数据到 buffer
response += buffer; // 将 buffer 的内容追加到 response
buffer.clear(); // 清空 buffer 以便下一次读取
}
// print the response
cout << response << endl;
}
int main(int argc, char* argv[]) {
try {
if (argc <= 0) {
abort(); // For sticklers: don't try to access argv[0] if argc <= 0.
}
auto args = span(argv, argc);
// The program takes two command-line arguments: the hostname and "path" part of the URL.
// Print the usage message unless there are these two arguments (plus the program name itself, so arg count = 3 in total).
if (argc != 3) {
cerr << "Usage: " << args.front() << " HOST PATH\n";
cerr << "\tExample: " << args.front() << " stanford.edu /class/cs144\n";
return EXIT_FAILURE;
}
// Get the command-line arguments.
const string host{args[1]};
const string path{args[2]};
// Call the student-written function.
get_URL(host, path);
} catch (const exception& e) {
cerr << e.what() << "\n";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
rain0832@ubuntu:~/CS144/minnow/build$ ./apps/webget cs144.keithw.org /hello
HTTP/1.1 200 OK
Date: Tue, 25 Feb 2025 12:21:33 GMT
Server: Apache
Last-Modified: Thu, 13 Dec 2018 15:45:29 GMT
ETag: "e-57ce93446cb64"
Accept-Ranges: bytes
Content-Length: 14
Connection: close
Content-Type: text/plain
Hello, CS144!
Function called: get_URL(cs144.keithw.org, /hello)
Warning: get_URL() has not been implemented yet.
rain0832@ubuntu:~/CS144/minnow/build$ ./apps/webget cs144.keithw.org /hello
HTTP/1.1 200 OK
Date: Tue, 25 Feb 2025 12:30:59 GMT
Server: Apache
Last-Modified: Thu, 13 Dec 2018 15:45:29 GMT
ETag: "e-57ce93446cb64"
Accept-Ranges: bytes
Content-Length: 14
Connection: close
Content-Type: text/plain
Hello, CS144!
#include "socket.hh"
#include <cstdlib>
#include <iostream>
#include <span>
#include <string>
using namespace std;
void get_URL( const string& host, const string& path )
{
// create TCP socket
TCPSocket socket;
// parse the address and connect
Address server_address(host, "http");
socket.connect(server_address);
// create HTTP request
string request = "GET " + path + " HTTP/1.1\r\n";
request += "Host: " + host + "\r\n";
request += "Connection: close\r\n\r\n";
// send the request
socket.write(request);
// read the response
string response;
string buffer;
while(!socket.eof())
{
socket.read(buffer);
response += buffer;
buffer.clear();
}
// extract the body part of the HTTP response
size_t body_start = response.find("\r\n\r\n") + 4;
if (body_start != string::npos)
{
cout <<response.substr(body_start);
}
else
{
// print the response
cout << response << endl;
}
}
int main( int argc, char* argv[] )
{
try {
if ( argc <= 0 ) {
abort(); // For sticklers: don't try to access argv[0] if argc <= 0.
}
auto args = span( argv, argc );
// The program takes two command-line arguments: the hostname and "path" part of the URL.
// Print the usage message unless there are these two arguments (plus the program name
// itself, so arg count = 3 in total).
if ( argc != 3 ) {
cerr << "Usage: " << args.front() << " HOST PATH\n";
cerr << "\tExample: " << args.front() << " stanford.edu /class/cs144\n";
return EXIT_FAILURE;
}
// Get the command-line arguments.
const string host { args[1] };
const string path { args[2] };
// Call the student-written function.
get_URL( host, path );
} catch ( const exception& e ) {
cerr << e.what() << "\n";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
rain0832@ubuntu:~/CS144/minnow$ cmake --build build --target check_webget
Test project /home/rain0832/CS144/minnow/build
Start 1: compile with bug-checkers
1/2 Test #1: compile with bug-checkers ........ Passed 0.71 sec
Start 2: t_webget
2/2 Test #2: t_webget ......................... Passed 2.26 sec
100% tests passed, 0 tests failed out of 2
Total Test time (real) = 2.98 sec
Built target check_webget
void push( std::string data );
// Push data to stream, but only as much as available capacity allows.
void close();
// Signal that the stream has reached its ending. Nothing more will be written.
bool is_closed() const;
// Has the stream been closed?
uint64_t available_capacity() const;
// How many bytes can be pushed to the stream right now?
uint64_t bytes_pushed() const;
// Total number of bytes cumulatively pushed to the stream
std::string_view peek() const;
// Peek at the next bytes in the buffer
void pop( uint64_t len );
// Remove `len` bytes from the buffer
bool is_finished() const;
// Is the stream finished (closed and fully popped)?
bool has_error() const;
// Has the stream had an error?
uint64_t bytes_buffered() const;
// Number of bytes currently buffered (pushed and not popped)
uint64_t bytes_popped() const;
// Total number of bytes cumulatively popped from stream
#pragma once
#include <cstdint>
#include <string>
#include <string_view>
class Reader;
class Writer;
class ByteStream
{
public:
explicit ByteStream( uint64_t capacity );
// Helper functions (provided) to access the ByteStream's Reader and Writer interfaces
Reader& reader();
const Reader& reader() const;
Writer& writer();
const Writer& writer() const;
void set_error() { error_ = true; }; // Signal that the stream suffered an error.
bool has_error() const { return error_; }; // Has the stream had an error?
protected:
// Please add any additional state to the ByteStream here, and not to the Writer and Reader interfaces.
uint64_t capacity_;
std::string buffer_;
uint64_t bytes_pushed_ {};
uint64_t bytes_popped_ {};
bool closed_flag_ {};
bool error_ {};
};
class Writer : public ByteStream
{
public:
void push( std::string data ); // Push data to stream, but only as much as available capacity allows.
void close(); // Signal that the stream has reached its ending. Nothing more will be written.
bool is_closed() const; // Has the stream been closed?
uint64_t available_capacity() const; // How many bytes can be pushed to the stream right now?
uint64_t bytes_pushed() const; // Total number of bytes cumulatively pushed to the stream
};
class Reader : public ByteStream
{
public:
std::string_view peek() const; // Peek at the next bytes in the buffer
void pop( uint64_t len ); // Remove `len` bytes from the buffer
bool is_finished() const; // Is the stream finished (closed and fully popped)?
uint64_t bytes_buffered() const; // Number of bytes currently buffered (pushed and not popped)
uint64_t bytes_popped() const; // Total number of bytes cumulatively popped from stream
};
/*
* read: A (provided) helper function thats peeks and pops up to `max_len` bytes
* from a ByteStream Reader into a string;
*/
void read( Reader& reader, uint64_t max_len, std::string& out );
rain0832@ubuntu:~/CS144/minnow$ cmake --build build --target check0
Test project /home/rain0832/CS144/minnow/build
Start 1: compile with bug-checkers
1/11 Test #1: compile with bug-checkers ........ Passed 28.10 sec
Start 2: t_webget
2/11 Test #2: t_webget ......................... Passed 4.14 sec
Start 3: byte_stream_basics
3/11 Test #3: byte_stream_basics ............... Passed 0.04 sec
Start 4: byte_stream_capacity
4/11 Test #4: byte_stream_capacity ............. Passed 0.03 sec
Start 5: byte_stream_one_write
5/11 Test #5: byte_stream_one_write ............ Passed 0.03 sec
Start 6: byte_stream_two_writes
6/11 Test #6: byte_stream_two_writes ........... Passed 0.02 sec
Start 7: byte_stream_many_writes
7/11 Test #7: byte_stream_many_writes .......... Passed 0.19 sec
Start 8: byte_stream_stress_test
8/11 Test #8: byte_stream_stress_test .......... Passed 0.06 sec
Start 37: no_skip
9/11 Test #37: no_skip .......................... Passed 0.02 sec
Start 38: compile with optimization
10/11 Test #38: compile with optimization ........ Passed 14.14 sec
Start 39: byte_stream_speed_test
ByteStream throughput (pop length 4096): 7.68 Gbit/s
ByteStream throughput (pop length 128): 1.79 Gbit/s
ByteStream throughput (pop length 32): 0.45 Gbit/s
11/11 Test #39: byte_stream_speed_test ........... Passed 0.78 sec
100% tests passed, 0 tests failed out of 11
Total Test time (real) = 47.57 sec
Built target check0