Autumn 2021
Jerry Cain
PDF
poohbear@myth64:~$ dig -t NS +noall +answer edu # where are the edu nameservers?
edu. 6691 IN NS k.edu-servers.net.
edu. 6691 IN NS i.edu-servers.net.
edu. 6691 IN NS c.edu-servers.net.
edu. 6691 IN NS h.edu-servers.net.
edu. 6691 IN NS d.edu-servers.net.
edu. 6691 IN NS b.edu-servers.net.
edu. 6691 IN NS a.edu-servers.net.
edu. 6691 IN NS f.edu-servers.net.
edu. 6691 IN NS m.edu-servers.net.
edu. 6691 IN NS l.edu-servers.net.
edu. 6691 IN NS e.edu-servers.net.
edu. 6691 IN NS j.edu-servers.net.
edu. 6691 IN NS g.edu-servers.net.
poohbear@myth64:~$ dig -t NS +noall +answer stanford.edu # the stanford.edu nameservers?
stanford.edu. 84428 IN NS ns6.dnsmadeeasy.com.
stanford.edu. 84428 IN NS argus.stanford.edu.
stanford.edu. 84428 IN NS avallone.stanford.edu.
stanford.edu. 84428 IN NS atalante.stanford.edu.
stanford.edu. 84428 IN NS ns7.dnsmadeeasy.com.
stanford.edu. 84428 IN NS ns5.dnsmadeeasy.com.
poohbear@myth64:~$ dig -t A +noall +answer web.stanford.edu # Where is web.stanford.edu?
web.stanford.edu. 431 IN A 171.67.215.200
poohbear~$ echo $HOSTNAME # note this, you need it for the telnet command below
myth64.stanford.edu
poohbear~$ nc -l 12345
Jerrys-MacBook-Pro:~ jerry$ nc myth64.stanford.edu 12345
int main(int argc, char *argv[]) {
int server = createServerSocket(12345);
while (true) {
int client = accept(server, NULL, NULL); // the two NULLs could instead be used to
// surface the IP address of the client
publishTime(client);
}
return 0;
}
publishTime
function is straightforward:static void publishTime(int client) {
time_t rawtime;
time(&rawtime);
struct tm *ptm = gmtime(&rawtime);
char timestr[128]; // more than big enough
/* size_t len = */ strftime(timestr, sizeof(timestr), "%c\n", ptm);
size_t numBytesWritten = 0, numBytesToWrite = strlen(timestr);
while (numBytesWritten < numBytesToWrite) {
numBytesWritten += write(client,
timestr + numBytesWritten,
numBytesToWrite - numBytesWritten);
}
close(client);
}
while
loop for writing bytes is a bit more important now that we are networking: we are more likely to need to write multiple times.
write
's return value could very well be less than what was supplied by the third argument. For example, you may try to publish the contents of a 62GB movie and be told that only 4MB went through.FILE *
) or C++ streams (e.g. the iostream
class hierarchy) to layer over data buffers and manage the while
loop around exposed write
calls for us.socket++
—that provides precisely this.
socket++
provides iostream subclasses that respond to operator<<
, operator>>
, getline
, endl
, and so forth, just as cin
, cout
, and file streams do.publishTime
.publishTime
:static void publishTime(int client) {
time_t rawtime;
time(&rawtime);
struct tm *ptm = gmtime(&rawtime);
char timestr[128]; // more than big enough
/* size_t len = */ strftime(timestr, sizeof(timestr), "%c", ptm);
sockbuf sb(client);
iosockstream ss(&sb);
ss << timestr << endl;
} // sockbuf destructor closes client
iosockstream
that itself layers over the client socket.sockbuf
class takes ownership of the socket and closes it when its destructor is called.myth-buster
and Assignment 5's aggregate
—where multithreading can significantly improve the performance of networked applications.accept
returns a socket descriptor, spawn a child thread—or reuse an existing one within a ThreadPool
—to get any intense, time consuming computation off of the main thread. The child thread can make use of a second processor or a second core, and the main thread can quickly move on to its next accept
call.ThreadPool
(you're implementing one for assign5) to get the computation off the main thread asap.int main(int argc, char *argv[]) {
int server = createServerSocket(12345);
ThreadPool pool(4);
while (true) {
int client = accept(server, NULL, NULL); // the two NULLs could instead be used
// to surface the IP address of the client
pool.schedule([client] { publishTime(client); });
}
return 0;
}
createClientSocket
. For now, view it as a built-in that sets up a bidirectional pipe between a client and a server running on the specified host (e.g. myth64
) and bound to the specified port number (e.g. 12345).int main(int argc, char *argv[]) {
int clientSocket = createClientSocket("myth64.stanford.edu", 12345);
assert(clientSocket >= 0);
sockbuf sb(clientSocket);
iosockstream ss(&sb);
string timeline;
getline(ss, timeline);
cout << timeline << endl;
return 0;
}