Short Answer Problems
- Cerf and Kahn’s 1974 paper, A Protocol for Packet Network Intercommunication. This paper was massively influential as it introduced what may have been the first cross-network protocol (a protocol allowing different networks to communicate with each other), enabling a truly world-wide computer network.
- Circuit switching in a network creates a dedicated path between the communicating hosts for a session. So all communication passes through the same intermediate points. Packet switching breaks up messages into packets and routes them dynamically from end to end. Packets in the same message may take different paths.
- According to Wikipedia, the Internet Engineering Task Force (IETF), the Internet Research Task Force (IRTF), the Internet Architecture Board (IAB), and independent authors are all sources of RFCs. The RFC system is supported by the Internet Society (ISOC). The IETF is the body that can accept an RFC as an Internet standard.
netstat -r
- The transport layer ensures data sent by an application is delivered to the correct application on the other end. This layer has knowledge not only of the Internet address but also the port number of the communicating hosts. On the sending side, the transport layer asks the network layer to deliver the packets (segments) to the receiving host. On the receiver, the transport layer passes the segments up to the application layer. Some protocols within the transport layer, like TCP, ensure reliable delivery (asking for retransmission and reassembling in order to provide a stream view to the application layer); other protocols, like UDP, do not.
- First message was 'L' and second was 'O'.
- TCP is reliable while UDP is not. TCP supports flow and congestion control, assembly of out of order packets, retransmission requests, and connection set up and tear down. UDP does not of those things.
- 20 bytes
- 60 bytes
- Node.js servers are event-driven and use a single thread for event handling.
Scripts
Random Number Server and Client
random_number_server.py
import socketserver
import random
class RandomHandler(socketserver.StreamRequestHandler):
def handle(self):
self.wfile.write(f'{random.randint(1, 1000)}\n'.encode('utf-8'))
with socketserver.TCPServer(('', 53211), RandomHandler) as server:
print('The random number server is running...')
server.serve_forever()
random_number_client.py
import sys
import socket
if len(sys.argv) != 2:
print('Pass the server IP as the sole command line argument')
else:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect((sys.argv[1], 53211))
print(sock.recv(1024).decode('utf-8'))
Echo Server and Client
echo_server.py
import socketserver
import threading
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
daemon_threads = True
allow_reuse_address = True
class EchoHandler(socketserver.StreamRequestHandler):
def handle(self):
client = f'{self.client_address} on {threading.currentThread().getName()}'
print(f'Connected: {client}')
while True:
data = self.rfile.readline()
if not data:
break
self.wfile.write(data)
print(f'Closed: {client}')
with ThreadedTCPServer(('', 43210), EchoHandler) as server:
print(f'The echo server is running...')
server.serve_forever()
echo_client.py
import sys
import socket
if len(sys.argv) != 2:
print('Pass the server IP as the sole command line argument')
else:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect((sys.argv[1], 43210))
print('Enter lines of text then Ctrl+D or Ctrl+C to quit')
while True:
line = sys.stdin.readline()
if not line:
# End of standard input, exit this entire script
break
sock.sendall(f'{line}'.encode('utf-8'))
while True:
data = sock.recv(128)
print(data.decode("utf-8"), end='')
if len(data) < 128:
# No more of this message, go back to waiting for next message
break
Chat Server
chat_server.py
import socketserver
import threading
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
daemon_threads = True
allow_reuse_address = True
names = set()
writers = set()
class ChatHandler(socketserver.StreamRequestHandler):
def handle(self):
client = f'{self.client_address} on {threading.currentThread().getName()}'
try:
while True:
self.wfile.write(f'SUBMITNAME\n'.encode('utf-8'))
name = self.rfile.readline().decode('utf-8').strip()
if name == "":
return
with threading.Lock():
if name != "" and name not in names:
names.add(name)
break
self.wfile.write(f'NAMEACCEPTED: {name}\n'.encode('utf-8'))
for w in writers:
w.write(f'MESSAGE {name} has joined\n'.encode('utf-8'))
writers.add(self.wfile)
while True:
message = self.rfile.readline().decode('utf-8')
if message.lower().startswith('/quit'):
return
for w in writers:
w.write(f'MESSAGE {name}: {message}\n'.encode('utf-8'))
except Exception as e:
print(e)
finally:
if self.wfile is not None:
writers.remove(self.wfile)
if name is not None:
names.remove(name)
for w in writers:
w.write(f'MESSAGE {name} has left\n'.encode('utf-8'))
if __name__ == '__main__':
with ThreadedTCPServer(('', 59001), ChatHandler) as server:
print(f'The chat server is running...')
server.serve_forever()