open connection then …
real Internet: mailbox-style communication
‘‘best-effort’’
sockets implemented on top of this
| application | HTTP, SSH, SMTP, … | application-defined meanings |
| transport | TCP, UDP, … | reach correct program reliability/streams |
| network | IPv4, IPv6 | reach correct machine (across networks) |
| link | Ethernet, Wi-Fi, … | coordinate shared wire/radio |
| physical | Ethernet, Wi-Fi, … | encode bits for wire/radio |
| application | application-defined meanings | |
| transport | reach correct program, reliablity/streams | segments/datagrams |
| network | reach correct machine (across networks) | packets |
| link | coordinate shared wire/radio | frames |
| physical | encode bits for wire/radio |
| A. | machine A needs to send ‘‘Got ‘got it!’ ’’ |
| B. | machine B should resend ‘‘Got it!’’ on its own |
| C. | machine A should resend the original message on its own |
| D. | none of these |
send ‘‘Got ‘got it!’ ’’?
resend ‘‘Got it!’’ own its own?
resend original message?
reconstructed message:
The meeting is at 12pm.
reconstructed message:
The meetingThe meeting is at 12pm.
| 1. | message (instead of acknowledgment) is lost |
| 2. | first message from machine A is delayed a long time by network |
| 3. | acknowledgment of second message lost instead of first |
reconstructed message:
The meeting is at 12pm.
reconstructed message:
The meeting is at 12pm.
A thinks: part 1 + part 2 acknowleged!
corruption: e.g., a bit flip
I LIKE CATS (49204C494B452043415453)I LIKE BATS (49204C494B452042415453)instead of sending ‘‘message’’, send ‘‘message’’ + checksum
I LIKE CATS) = 0xD949204C494B452043415453D9
receiver then also computes the checksum with the same data
Send a window of parts speculatively, then wait for ACKs.
| application | HTTP, SSH, SMTP, … | application-defined meanings |
| transport | TCP, UDP, … | reach correct program reliability/streams |
| network | IPv4, IPv6 | reach correct machine (across networks) |
| link | Ethernet, Wi-Fi, … | coordinate shared wire/radio |
| physical | Ethernet, Wi-Fi, … | encode bits for wire/radio |
TCP: stream to other program
UDP: messages sent to program, but no reliablity/streams
unreliable transmission of short messages
write(fd, “a”, 1); write(fd, “b”, 1) \(\not=\) write(fd, “ab”, 2)
‘‘connecting’’ just sets default destination
can sendto()/recvfrom() multiple other programs with one socket
request + receive message split into pieces
you are responsible for:
‘‘acknowledge’’ receiving part X to request part X+1
GET(x) — retrieve message \(x\) (x = 0, 1, 2, or 3)
ACK(n)
/* library code you don't write */
/* lab: part of waitForAllTimeoutsAndMessagesThenExit() */
void mainLoop() {
while (notExiting) {
Event event = waitForAndGetNextEvent();
if (event.type == RECIEVED) {
recvd(...);
} else if (event.type == TIMEOUT) {
(event.timeout_function)(...);
}
...
}
}
/* your code, called by library */
void recvd(...) {
...
setTimeout(..., timerCallback, ...);
}
void timerCallback(...) {
...
}
int main() {
send(.../* first message */);
... /* other initial setup */
waitForAllTimeoutsAndMessagesThenExit(); // runs mainLoop()
}
packet = getNextPacket()
doSomething(packet);
sleep(10);
doAnotherThing();
packet = getNextPacket();
doYetAnotherThing(packet);
turns into code like:
afterTimeout() {
doAnotherThing(); mode = 2;
}
recvdPacket(packet) {
if (mode == 1) {
doSomething(packet);
setTimeout(10, afterTimeout);
} else if (mode == 2)
doYetAnotherThing(packet);
} else ...
}
| name | address |
| logical identifier | location/how to locate |
variable counter
|
memory address 0x7FFF9430
|
DNS name www.virginia.edu
|
IPv4 address 128.143.22.36
|
DNS name mail.google.com
|
IPv4 address 216.58.217.69
|
DNS name mail.google.com
|
IPv6 address 2607:f8b0:4004:80b::2005
|
DNS name cso2.cs.virginia.edu
|
IPv4 address 128.143.67.91
|
DNS name cso2.cs.virginia.edu
|
MAC address 18:66:da:2e:7f:da
|
service name https
|
port number 443
|
service name ssh
|
port number 22
|
the Internet Protocol (IP) version 4 or version 6
allows send messages to/recv messages from other networks
messages called ‘‘packets’’
32-bit numbers
typically written like 128.143.67.11
organizations get blocks of IPs
some IPs reserved for non-Internet use (127.x.x.x, 10.x.x.x, 192.168.x.x, …)
IPv6 like IPv4, but with 128-bit numbers
written in hex, 16-bit parts, seperated by colons (:)
strings of 0s represented by double-colons (::)
typically given to users in blocks of \(2^{80}\) or \(2^{64}\) addresses
2607:f8b0:400d:c00::6a =
2607:f8b0:400d:0c00:0000:0000:0000:006a
2607f8b0400d0c0000000000000006a\(_\text{SIXTEEN}\)IP addresses identify machines on the global internet
address grouped geographically
routing: finding a path for packets from source to destination across internet
analogy: airplane routing
routing protocols determine routes from all sources to all destinations
| application | HTTP, SSH, SMTP, … | application-defined meanings |
| transport | TCP, UDP, … | reach correct program reliability/streams |
| network | IPv4, IPv6 | reach correct machine (across networks) |
| link | Ethernet, Wi-Fi, … | coordinate shared wire/radio |
| physical | Ethernet, Wi-Fi, … | encode bits for wire/radio |
connection identified by 4-tuple
(local IP address, local port, remote IP address, remote port)
local IP address, port number can be set with bind() function
we run multiple programs on a machine
so, add 16-bit port numbers
0–49151: typically assigned for particular services
49152–65535: allocated on demand
| name | address |
| logical identifier | location/how to locate |
variable counter
|
memory address 0x7FFF9430
|
DNS name www.virginia.edu
|
IPv4 address 128.143.22.36
|
DNS name mail.google.com
|
IPv4 address 216.58.217.69
|
DNS name mail.google.com
|
IPv6 address 2607:f8b0:4004:80b::2005
|
DNS name cso2.cs.virginia.edu
|
IPv4 address 128.143.67.91
|
DNS name cso2.cs.virginia.edu
|
MAC address 18:66:da:2e:7f:da
|
service name https
|
port number 443
|
service name ssh
|
port number 22
|
Uniform Resource Locators (URL)
Unifrom Resources Identifiers
https://kytos02.cs.virginia.edu:443/cs3130-spring2023/quizzes/quiz.php?qid=02#q2
https://kytos02.cs.virginia.edu/cs3130-spring2023/quizzes/quiz.php?qid=02
https://www.cs.virginia.edu/
sftp://cr4bd@portal.cs.virginia.edu/u/cr4bd/file.txt
tel:+1-434-982-2200
//www.cs.virginia.edu/~cr4bd/3130/S2023/
/~cr4bd/3130/S2023
scheme://authority/path?query#fragment
scheme: — what protocol
//authority/
path
?query — usually key/value pairs
#fragment — place in resource
most components (sometimes) optional
primary application-layer protocol for the Web
text-based protocol
standard port: 80 (non-encrypted), 443 (encrypted)
uses TCP (or TCP + TLS for encrypted version)
client-server protocol
ex. URL: http://www.foo.com/bar
http://www.foo.com/bar
HTTP client (example: web browser):
does a DNS lookup for www.foo.com (gets 123.156.189.12)
connects via TCP to 123.156.189.12 port 80
sends something like:
GET /bar HTTP/1.1
Host: www.foo.com
...server replies with status code + (usually) some data
GET — get resource
POST — sending forms
HEAD — get metadata about file (without getting its data)
PUT, DELETE, …
all requests/replies have many possible headers
| application | HTTP, SSH, SMTP, … | application-defined meanings |
| transport | TCP, UDP, … | reach correct program reliability/streams |
| network | IPv4, IPv6 | reach correct machine (across networks) |
| link | Ethernet, Wi-Fi, … | coordinate shared wire/radio |
| physical | Ethernet, Wi-Fi, … | encode bits for wire/radio |
ran out of IPv4 addresses
possible solutions:
convert many private addresses to one public address
commonly how home networks work (and some ISPs)
certain IPv4 address blocks reserved for private/internal use
192.168.X.X172.16.X.X–172.31.X.X10.X.X.XNAT illusion:
private IP address communicating directly with public IP
inside network, talking to outside:
outside network, talking to inside
| remote host + port | outside local port number | inside IP | inside port number |
| 128.148.17.3:443 | 54033 | 192.168.1.5 | 43222 |
| 11.7.17.3:443 | 53037 | 192.168.1.5 | 33212 |
| 128.148.31.2:22 | 54032 | 192.168.1.37 | 43010 |
| 128.148.17.3:443 | 63039 | 192.168.1.37 | 32132 |
| application | HTTP, SSH, SMTP, … | application-defined meanings |
| transport | TCP, UDP, … | reach correct program reliability/streams |
| network | IPv4, IPv6 | reach correct machine (across networks) |
| link | Ethernet, Wi-Fi, … | coordinate shared wire/radio |
| physical | Ethernet, Wi-Fi, … | encode bits for wire/radio |
\begin{center}
{}
\end{center}
\begin{center}
{}
\end{center}
\begin{center}
{}
\end{center}
Ethernet, Wi-Fi, Bluetooth, DOCSIS (cable modems), …
allows send/recv messages to machines on ‘‘same’’ network segment
typically: source+destination specified with MAC addresses
can specify destination of ‘‘anyone’’ (called broadcast)
messages usually called ‘‘frames’’
divide raw bits into messages
identify who message is for on shared radio/wire
handle if two+ machines use radio/wire at same time
drop/resend messages if corruption detected
Ethernet + Wifi have checksums
Q1: Why doesn’t this give us uncorrupted messages?
Q2: What’s a benefit of doing this if we’re also doing it in the higher layer?
| event | on Ethernet | on WiFi |
| collides with another | detected + may resend | resend |
| not received | lose silently | resent |
| header corrupted | usually discard silently | usually resend |
| data corrupted | usually discard silently | usually resend |
| too long | not allowed to send | not allowed to send |
| reordered (v. other messages) | received out of order | received out of order |
| destination unknown | lose silently | usually resend?? |
| too much being sent | discard excess? | discard excess? |
| event | on IPv4/v6 |
| collides with another | out of scope — handled by link layer |
| not received\tikzmark{not recv} | lost silently |
| header corrupted | usually discarded silently |
| data corrupted | received corrupted |
| too long | dropped with notice or ‘‘fragmented’’ + recombined |
| reordered (v. other messages) | received out of order |
| destination unknown | usually dropped with notice |
| too much being sent | discard excess |
don’t want to expose network service to everyone?
solutions:
later two called ‘‘firewalls’’
TIME_WAIT, ESTABLISHED, …?
OS tracks ‘‘state’’ of TCP connection
standardized set of state names
remember delayed messages?
problem for TCP ports
if I reuse port number, I can get message from old connection
solution: TIME_WAIT to make sure connection really done
$ dig +trace +all www.cs.virginia.edu
...
edu. 172800 IN NS b.edu-servers.net.
edu. 172800 IN NS f.edu-servers.net.
edu. 172800 IN NS i.edu-servers.net.
edu. 172800 IN NS a.edu-servers.net.
...
b.edu-servers.net. 172800 IN A 191.33.14.30
b.edu-servers.net. 172800 IN AAAA 2001:503:231d::2:30
f.edu-servers.net. 172800 IN A 192.35.51.30
f.edu-servers.net. 172800 IN AAAA 2001:503:d414::30
...
;; Received 843 bytes from 198.97.190.53#53(h.root-servers.net) in 8 ms
...
$ dig +trace +all www.cs.virginia.edu
...
virginia.edu. 172800 IN NS nom.virginia.edu.
virginia.edu. 172800 IN NS uvaarpa.virginia.edu.
virginia.edu. 172800 IN NS eip-01-aws.net.virginia.edu.
nom.virginia.edu. 172800 IN A 128.143.107.101
uvaarpa.virginia.edu. 172800 IN A 128.143.107.117
eip-01-aws.net.virginia.edu. 172800 IN A 44.234.207.10
;; Received 165 bytes from 192.26.92.30#53(c.edu-servers.net) in 40 ms
...
$ dig +trace +all www.cs.virginia.edu
...
cs.virginia.edu. 3600 IN NS coresrv01.cs.virginia.edu.
coresrv01.cs.virginia.edu. 3600 IN A 128.143.67.11
;; Received 116 bytes from 44.234.207.10#53(eip-01-aws.net.virginia.edu) in 72 ms
www.cs.Virginia.EDU. 172800 IN A 128.143.67.11
cs.Virginia.EDU. 172800 IN NS coresrv01.cs.Virginia.EDU.
coresrv01.cs.Virginia.EDU. 172800 IN A 128.143.67.11
;; Received 151 bytes from 128.143.67.11#53(coresrv01.cs.virginia.edu) in 4 ms
$ dig www.cs.virginia.edu
...
;; ANSWER SECTION:
www.cs.Virginia.EDU. 7183 IN A 128.143.67.11
..
int fd = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in my_addr= ...;
/* set local IP address + port */
bind(fd, &my_addr, sizeof(my_addr))
struct sockaddr_in to_addr = ...;
connect(fd, &to_addr); /* set remote IP address + port */
/* doesn't actually communicate with remote address yet */
...
int count = write(fd, data, data_size);
// OR
int count = send(fd, data, data_size, 0 /* flags */);
/* single message -- sent ALL AT ONCE */
int count = read(fd, buffer, buffer_size);
// OR
int count = recv(fd, buffer, buffer_size, 0 /* flags */);
/* receives whole single message ALL AT ONCE */
int fd = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in my_addr= ...;
/* set local IP address + port */
if (0 != bind(fd, &my_addr, sizeof(my_addr)))
handle_error();
...
struct sockaddr_in to_addr = ...;
/* send a message to specific address */
int bytes_sent = sendto(fd, data, data_size, 0 /* flags */,
&to_addr, sizeof(to_addr));
struct sockaddr_in from_addr = ...;
/* receive a message + learn where it came from */
int bytes_recvd = recvfrom(fd, &buffer[0], buffer_size, 0,
&from_addr, sizeof(from_addr));
...
when configuring network specify:
range of addresses to expect on local network
gateway machine to send to for things outside my local network
$ /sbin/route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 128.143.67.1 0.0.0.0 UG 100 0 0 enp0s31f6
128.143.67.0 0.0.0.0 255.255.255.0 U 100 0 0 enp0s31f6
169.254.0.0 0.0.0.0 255.255.0.0 U 1000 0 0 enp0s31f6
network configuration says:
(line 2) to get to 128.143.67.0–128.143.67.255, send directly on local network
(line 3) to get to 169.254.0.0–169.254.255.255, send directly on local network
(line 1) to get anywhere else, use ‘‘gateway’’ 128.143.67.1
my desktop:
$ arp -an
? (128.143.67.140) at 3c:e1:a1:18:bd:5f [ether] on enp0s31f6
? (128.143.67.236) at <incomplete> on enp0s31f6
? (128.143.67.11) at 30:e1:71:5f:39:10 [ether] on enp0s31f6
? (128.143.67.92) at <incomplete> on enp0s31f6
? (128.143.67.5) at d4:be:d9:b0:99:d1 [ether] on enp0s31f6
…
network address to link-layer address + interface
only tracks things directly connected to my local network
http://www.foo.com:80/foo/bar?quux#q1GET /foo/bar?quux HTTP/1.1
Host: \\emphThree{www.foo.com:80}
int server_socket_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY; /* "any address I can use" */
/* or: addr.s_addr.in_addr = INADDR_LOOPBACK (127.0.0.1) */
/* or: addr.s_addr.in_addr = htonl(...); */
addr.sin_port = htons(9999); /* port number 9999 */
if (bind(server_socket_fd, &addr, sizeof(addr)) < 0) {
/* handle error */
}
listen(server_socket_fd, MAX_NUM_WAITING);
...
int socket_fd = accept(server_socket_fd, NULL);
int sock_fd;
server = /* code on later slide */;
sock_fd = socket(
AF_INET, /* IPv4 */
SOCK_STREAM, /* byte-oriented */
IPPROTO_TCP
);
if (sock_fd < 0) { /* handle error */ }
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(2156872459); /* 128.143.67.11 */
addr.sin_port = htons(80); /* port 80 */
if (connect(sock_fd, (struct sockaddr*) &addr, sizeof(addr)) {
/* handle error */
}
DoClientStuff(sock_fd); /* read and write from sock_fd */
close(sock_fd);
void client_for_connection(int socket_fd) {
int n; char send_buf\[MAX_SIZE]; char recv_buf\[MAX_SIZE];
while (prompt_for_input(send_buf, MAX_SIZE)) {
n = write(socket_fd, send_buf, strlen(send_buf));
if (n != strlen(send_buf)) {...error?...}
n = read(socket_fd, recv_buf, MAX_SIZE);
if (n <= 0) return; // error or EOF
write(STDOUT_FILENO, recv_buf, n);
}
}
void server_for_connection(int socket_fd) {
int read_count, write_count; char request_buf\[MAX_SIZE];
while (1) {
read_count = read(socket_fd, request_buf, MAX_SIZE);
if (read_count <= 0) return; // error or EOF
write_count = write(socket_fd, request_buf, read_count);
if (read_count != write_count) {...error?...}
}
}
/* example (hostname, portname) = ("127.0.0.1", "443") */
const char *hostname; const char *portname;
...
struct addrinfo *server;
struct addrinfo hints;
int rv;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET; /* for IPv4 */
/* or: */ hints.ai_family = AF_INET6; /* for IPv6 */
/* or: */ hints.ai_family = AF_UNSPEC; /* I don't care */
hints.ai_flags = AI_PASSIVE;
rv = getaddrinfo(hostname, portname, &hints, &server);
if (rv != 0) { /* handle error */ }
struct addrinfo *server;
... getaddrinfo(...) ...
int server_socket_fd = socket(
server->ai_family,
server->ai_sockttype,
server->ai_protocol
);
if (bind(server_socket_fd, ai->ai_addr, ai->ai_addr_len)) < 0) {
/* handle error */
}
listen(server_socket_fd, MAX_NUM_WAITING);
...
int socket_fd = accept(server_socket_fd, NULL);
int sock_fd;
struct addrinfo *server = /* code on next slide */;
sock_fd = socket(
server->ai_family,
// ai_family = AF_INET (IPv4) or AF_INET6 (IPv6) or ...
server->ai_socktype,
// ai_socktype = SOCK_STREAM (bytes) or ...
server->ai_prototcol
// ai_protocol = IPPROTO_TCP or ...
);
if (sock_fd < 0) { /* handle error */ }
if (connect(sock_fd, server->ai_addr, server->ai_addrlen) < 0) {
/* handle error */
}
freeaddrinfo(server);
DoClientStuff(sock_fd); /* read and write from sock_fd */
close(sock_fd);
/* example hostname, portname = "www.cs.virginia.edu", "443" */
const char *hostname; const char *portname;
...
struct addrinfo *server;
struct addrinfo hints;
int rv;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; /* for IPv4 OR IPv6 */
// hints.ai_family = AF_INET4; /* for IPv4 only */
hints.ai_socktype = SOCK_STREAM; /* byte-oriented --- TCP */
rv = getaddrinfo(hostname, portname, &hints, &server);
if (rv != 0) { /* handle error */ }
/* eventually freeaddrinfo(result) */
struct addrinfo *server;
...
rv = getaddrinfo(hostname, portname, &hints, &server);
if (rv != 0) { /* handle error */ }
for (struct addrinfo *current = server; current != NULL;
current = current->ai_next) {
sock_fd = socket(current->ai_family, current->ai_socktype, current->ai_protocol);
if (sock_fd < 0) continue;
if (connect(sock_fd, current->ai_addr, current->ai_addrlen) == 0) {
break;
}
close(sock_fd); // connect failed
}
freeaddrinfo(server);
DoClientStuff(sock_fd);
close(sock_fd);
/* example hostname, portnum= "www.cs.virginia.edu", 443*/
const char *hostname; int portnum;
...
struct hostent *server_ip;
server_ip = gethostbyname(hostname);
if (server_ip == NULL) { /* handle error */ }
struct sockaddr_in addr;
addr.s_addr = *(struct in_addr*) server_ip->h_addr_list[0];
addr.sin_port = htons(portnum);
sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
connect(sock_fd, &addr, sizeof(addr));
...
Unix convention: must be root to use ports 0–1023
so, for testing: probably ports \(>\) 1023