{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Network and web technologies\n", "\n", "(I.e. how can we interact with services on other computers from Python?)\n", "\n", "[Teletype machines](https://en.wikipedia.org/wiki/Teleprinter) \"were adapted to provide a user interface to early mainframe computers and minicomputers, sending typed data to the computer and printing the response.\"\n", "\n", "![WACsOperateTeletype.jpg](WACsOperateTeletype.jpg) WWII era teletype machines. \n", "Source: https://commons.wikimedia.org/wiki/File:WACsOperateTeletype.jpg" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Let's start with an idealized \"serial port\"\n", "\n", "![serial-port.png](serial-port.png)\n", "\n", "Data is carried as a *serial* stream of bits (1s and 0s, high and low voltage).\n", "\n", "We can think about teletype machines, USB, ethernet cables, WiFi/WLAN, and so on:\n", "\n", "(From https://www.electroschematics.com/wp-content/uploads/2010/01/usb-wiring-connection.jpg?fit=1024%2C768)\n", "![usb-wiring-connection.jpg](usb-wiring-connection.jpg)\n", "\n", "![receiver-wiring-to-FC.png](receiver-wiring-to-FC.png) Source: https://www.expresslrs.org/quick-start/receivers/wiring-up/\n", "\n", "(Ethernet cables get more sophisticated. https://serverfault.com/questions/449416/why-do-ethernet-cables-have-8-wires . This is a theme that repeats itself in computer networking.)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "But this is not a \"network\", only two computers\n", "\n", "## From serial to network\n", "\n", "We can build a robust network composed of many individual serial links by defining a common language -- namely packets with framing information - such as a destination address - and a payload. The individual nodes in the network use the framing information to forward the packet or to consume it.\n", "\n", "This standardization has allowed hardware and software producers to interoperate by having common interfaces. Here is an ethernet frame:\n", "\n", "![Ethernet_Type_II_Frame_format.svg.png](Ethernet_Type_II_Frame_format.svg.png) Source: https://commons.wikimedia.org/wiki/File:Ethernet_Type_II_Frame_format.svg\n", "\n", "USB also uses the idea of frames to establish a standard for a robust single link \"network\". Here is a USB frame:\n", "\n", "![640px-USB_signal_example.svg.png](640px-USB_signal_example.svg.png) \"Data packets would have address field and payload between the packet ID and the end of packet.\" Source: https://commons.wikimedia.org/wiki/File:USB_signal_example.svg\n", "\n", "![640px-Speedport_W_921V,_Deutsche_Telekom-7294.jpg](640px-Speedport_W_921V,_Deutsche_Telekom-7294.jpg)\n", "Source: https://de.m.wikipedia.org/wiki/Datei:Speedport_W_921V,_Deutsche_Telekom-7294.jpg\n", "\n", "![640px-Speedport_W_921V,_Deutsche_Telekom-7296.jpg](640px-Speedport_W_921V,_Deutsche_Telekom-7296.jpg)\n", "Source: https://commons.wikimedia.org/wiki/File:Speedport_W_921V,_Deutsche_Telekom-7296.jpg\n", "\n", "\n", "![Wireless-router-network-diagram.png](Wireless-router-network-diagram.png) Source: https://www.conceptdraw.com/How-To-Guide/what-is-a-wireless-network" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# DHCP - Dynamic Host Configuration Protocol\n", "\n", "DHCP is the protocol used when your computer first joins a network and asks for an IP address.\n", "\n", "![DHCP-protocol.png](DHCP-protocol.png) Source: https://www.boardinfinity.com/blog/dynamic-host-configuration-protocol-dhcp/" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Layers of networking\n", "\n", "![UDP_encapsulation.png](UDP_encapsulation.png)\n", "Source: https://en.wikipedia.org/wiki/File:UDP_encapsulation.png\n", "\n", "From http://www.cellbiol.com/bioinformatics_web_development/chapter-1-internet-networks-and-tcp-ip/the-tcpip-family-of-internet-protocols/\n", "\n", "![tpc-ip-and-osi-model-cellbiol.com_.png](tpc-ip-and-osi-model-cellbiol.com_.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "These notes give an overview of the most important of these levels with the idea of understanding what your computer is doing when you use the web browser or how a program you write would interact automatically with, for example, a remote server to perform a BLAST query." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## TCP and UDP\n", "\n", "From https://microchipdeveloper.com/tcpip:tcp-vs-udp\n", "![tcp-vs-udp.jpg](tcp-vs-udp.jpg)\n", "\n", "In addition to source and destination address, TCP and UDP frames have \"port\" and thus address has a 2^16 (65536) TCP ports and 2^16 UDP ports." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "UDP joke https://micromismanagement.com/cartoons/udp/\n", "\n", "![udp-joke.png](udp-joke.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Socket\n", "\n", "From https://www.codeproject.com/Articles/1264257/Socket-Programming-in-Cplusplus-using-boost-asio-T\n", "\n", "![socket.png](socket.png)\n", "\n", "From http://ithare.com/network-programming-socket-peculiarities-threads-and-testing/\n", "\n", "![socket-cartoon.png](socket-cartoon.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# DNS and IP addresses\n", "\n", "From https://blog.octo.com/en/comic-introduction-to-networks-ip-addresses/\n", "\n", "![dns-ip.png](dns-ip.png)\n", "\n", "From https://foxutech.com/what-is-dns-and-how-it-works/\n", "\n", "![dns.webp](dns.webp)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "DNS https://howdns.works/" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "https://ruslanspivak.com/lsbaws-part1/\n", "\n", "https://jvns.ca/blog/2019/09/06/how-to-put-an-html-page-on-the-internet/\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Image source https://twitter.com/b0rk/status/1161997141876903936 (linked from [Julia Evans' blog](https://jvns.ca/blog/2019/09/12/new-zine-on-http/))\n", "\n", "![urls.jpg](urls.jpg)\n", "\n", "# -----\n", "\n", "Image source https://ruslanspivak.com/lsbaws-part1/\n", "\n", "![web-server.png](web-server.png)\n", "\n", "# -----\n", "\n", "Image source https://twitter.com/b0rk/status/1155318552129396736\n", "\n", "![http-basics.jpg](http-basics.jpg)\n", "\n", "# -----\n", "\n", "Image source https://twitter.com/b0rk/status/1145362860136177664\n", "\n", "![anatomy-of-http-request.jpg](anatomy-of-http-request.jpg)\n", "\n", "\n", "# -----\n", "\n", "Image source https://twitter.com/b0rk/status/1161679906415218690\n", "\n", "![http-request-methods.jpg](http-request-methods.jpg)\n", "\n", "# -----\n", "\n", "Image source https://twitter.com/b0rk/status/1145896193077256197\n", "\n", "![http-response-methods.jpg](http-response-methods.jpg)\n", "\n", "# -----\n", "\n", "Image source https://twitter.com/b0rk/status/1146054159214567424\n", "\n", "![post-requests.jpg](post-requests.jpg)\n", "\n", "# -----\n", "\n", "Image source https://twitter.com/b0rk/status/1159839824594915335\n", "\n", "![http-exercises.jpg](http-exercises.jpg)\n", "\n", "# -----\n", "\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", " \n", " \n", "
404. That’s an error.\n", "
The requested URL /bananas
was not found on this server. That’s all we know.\n"
]
}
],
"source": [
"!curl http://google.com/bananas"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's practice with the [Star Wars API](https://swapi.py4e.com/).\n",
"\n",
"```curl https://swapi.py4e.com/api/people/1/```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We will use the [requests](https://pypi.org/project/requests/) library."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"import requests"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'{\"name\":\"Darth Vader\",\"height\":\"202\",\"mass\":\"136\",\"hair_color\":\"none\",\"skin_color\":\"white\",\"eye_color\":\"yellow\",\"birth_year\":\"41.9BBY\",\"gender\":\"male\",\"homeworld\":\"https://swapi.py4e.com/api/planets/1/\",\"films\":[\"https://swapi.py4e.com/api/films/1/\",\"https://swapi.py4e.com/api/films/2/\",\"https://swapi.py4e.com/api/films/3/\",\"https://swapi.py4e.com/api/films/6/\"],\"species\":[\"https://swapi.py4e.com/api/species/1/\"],\"vehicles\":[],\"starships\":[\"https://swapi.py4e.com/api/starships/13/\"],\"created\":\"2014-12-10T15:18:20.704000Z\",\"edited\":\"2014-12-20T21:17:50.313000Z\",\"url\":\"https://swapi.py4e.com/api/people/4/\"}'"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"response = requests.get('https://swapi.py4e.com/api/people/4/')\n",
"response.text"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"requests.models.Response"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"type(response)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"str"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"type(response.text)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'Date': 'Fri, 10 Jan 2025 09:07:09 GMT', 'Content-Type': 'application/json', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Vary': 'Accept-Encoding, Accept, Cookie', 'X-Frame-Options': 'SAMEORIGIN', 'ETag': 'W/\"84f396e29689886d73163ffeea41d4b8\"', 'Allow': 'GET, HEAD, OPTIONS', 'X-Clacks-Overhead': 'GNU Terry Pratchett', 'Content-Encoding': 'gzip', 'Age': '10', 'Cache-Control': 'max-age=14400', 'cf-cache-status': 'HIT', 'Report-To': '{\"endpoints\":[{\"url\":\"https:\\\\/\\\\/a.nel.cloudflare.com\\\\/report\\\\/v4?s=k1tyqow%2BTHfXBggdLlKOGfY3YUvPQIZw2P1EowugfuLk%2F2nzXWw0X%2FjfUeLAhQcRikRxCoEH%2FDEcASi998U%2FcN70vLqQIRPjvoxABihBwDr9ApD2b%2BpBaqDMJ2ujpKeewA%3D%3D\"}],\"group\":\"cf-nel\",\"max_age\":604800}', 'NEL': '{\"success_fraction\":0,\"report_to\":\"cf-nel\",\"max_age\":604800}', 'Server': 'cloudflare', 'CF-RAY': '8ffb83dfbba02c0a-STR', 'alt-svc': 'h3=\":443\"; ma=86400', 'server-timing': 'cfL4;desc=\"?proto=TCP&rtt=4615&min_rtt=4583&rtt_var=1314&sent=4&recv=7&lost=0&retrans=0&sent_bytes=2830&recv_bytes=781&delivery_rate=630387&cwnd=251&unsent_bytes=0&cid=59f4e5c9b008e54f&ts=22&x=0\"'}"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"response.headers"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'name': 'Darth Vader',\n",
" 'height': '202',\n",
" 'mass': '136',\n",
" 'hair_color': 'none',\n",
" 'skin_color': 'white',\n",
" 'eye_color': 'yellow',\n",
" 'birth_year': '41.9BBY',\n",
" 'gender': 'male',\n",
" 'homeworld': 'https://swapi.py4e.com/api/planets/1/',\n",
" 'films': ['https://swapi.py4e.com/api/films/1/',\n",
" 'https://swapi.py4e.com/api/films/2/',\n",
" 'https://swapi.py4e.com/api/films/3/',\n",
" 'https://swapi.py4e.com/api/films/6/'],\n",
" 'species': ['https://swapi.py4e.com/api/species/1/'],\n",
" 'vehicles': [],\n",
" 'starships': ['https://swapi.py4e.com/api/starships/13/'],\n",
" 'created': '2014-12-10T15:18:20.704000Z',\n",
" 'edited': '2014-12-20T21:17:50.313000Z',\n",
" 'url': 'https://swapi.py4e.com/api/people/4/'}"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x = response.json()\n",
"x"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"