The project requires that you use the Hyper-Text Transport Protocol (HTTP) and Hyper-Text Meta-Language (HTML) protocols within a Transmission Control Protocol (TCP) over Internet Protocol (IP) connection for communication between the web-browser and each station server. Very simple HTTP exchanges and simple HTML content are sufficient. Your HTML content (text) is embedded within the payload of HTTP, which is embedded within the payload of TCP, which is embedded within the payload of IP, which (normally) would be embedded within the payload of an Ethernet frame. However, our project's network traffic never leaves your single computer, so the IP packets are queued and exchanged through your computer's RAM.
Network traffic across a TCP/IP connection is bi-directional and reliable - one end writes a query, the other end reads the (uncorrupted) arriving query, determines/calculates a response, writes that response, and the other (original) end reads it. Both ends can write data at the same time - the two messages do not interfere with each other when 'crossing'.
OK, let's find an available port-number - meaning, one not currently in use
by another process.
Download this Linux/macOS bash shellscript portsinuse.sh (which will probably download when you click on the link), make it executable, and run it:
shell> chmod +x portsinuse.sh
Choose a port-number not listed there (and above 1023), say 4444, and run the command:
shell> nc -l 4444
You've just started a new server process, listening on port 4444, and expecting a connection and network traffic using TCP/IP (the default). Ahh, this project looks easy!
Now let's use your web-browser, acting as a TCP/IP-based client, to connect to that nc server. Because (assuming) your web-browser and the nc process are running on the same computer, each will be able to communicate using the 'generic' hostname of localhost (or, depending on your computer's configuration, you may need to use the IP address 127.0.0.1).
Open a new tab in your browser,
and in the address bar enter the URL
(that's http colon, not https colon - don't believe how your browser renders this webpage!)
In the shell window of your nc process you should immediately see what the browser has sent to nc, commencing with:
GET / HTTP/1.1
The 8 or so lines you see is a basic HTTP header (version 1.1), followed by a blank line. Your web-browser is still waiting for a reply from nc, so we need to also reply using HTTP. Type (cut-and-paste) in your shell window:
HTTP/1.1 200 OK
<h1>Hello from nc!</h1>
and then control-C or control-D to terminate the TCP/IP connection between nc and web-browser. You've replied with an HTTP header (version 1.1), indicating that the 'request' was valid and understood (reply code 200), indicated that the type of your reply will be HTML (case is insigificant), and eventually sent 5 lines of HTML. You should see the reply rendered in your browser's tab.
Now, repeat the whole exercise, re-running nc and this time requesting the URL https://localhost:4444/?to=Perth_Stn into your browser. You should see this new request arrive with:
GET /?to=Perth_Stn HTTP/1.1
Hmmm now, if only nc was actually our own station server program, written in Java, or C, or Python, we might know what to do with the request, and what to write back as our reply!
While this part of the project involves sending an HTTP request over a TCP/IP connection, and sending an HTTP reply carrying an HTML message back across the same TCP/IP connection, we've almost finished it without having written a line of code. Of course, we need to replicate some of the work that nc performed in establishing the server's connection on our chosen port-number (4444), and that's where our first bit of coding becomes programming-language specific.
Consider the following excellent diagram of a simple 4-station network:
The above network requires 4 distinct operating system processes to execute, each written in your choice of two programming languages. We can invoke all of these processes from the command-line, or from a shellscript, as below. Each process receives a small number of command-line arguments, providing its station's name, its unique port for TCP/IP-based communication with a web-browser, its unique port for UDP/IP-based communication with other stations using datagrams, the UDP/IP-based port(s) of directly connected (neighbour) stations. Notice, also, that all processes have been 'started in the background', because none needs to remain connected to the invoking keyboard.
./station North_Terminus 2210 2608 2606 &
shell> ./station East_Station 2230 2606 2608 2602 2605 &
shell> ./station.py West_Station 2220 2602 2605 2606 &
shell> ./station.py South_Busport 2240 2605 2606 2602 &
When invoked, each station process first initialises its TCP and UDP ports, and then reads a comma-separated textfile providing its own timetable information. While your servers will need to read in and parse the contents of the timetable files, you can assume that all their contents are correct (time-formats are correct, departure times precede arrival times, destination station names exist, etc). For example, the file tt-North_Terminus may contain lines of the form:
The first line contains the station's name (also forming the filename), and latitude and longitude (which you can ignore, though some students wanted to drap a map on their webpages! :-) The second and subsequent lines each define a single bus connection leaving the station. The second line can be read as: "At 7.15am, bus number 12 leaves Stop1, arriving at 7.54am at East_Station". Note that there is no networking information (protocols or ports) in the file, and that North_Terminus does not know anything about West_Station or South_Busport.
The file tt-East_Station will have exactly the same format, but likely have more timetable entries because it has more direct connections.
East_Station North_Terminus South_Busport West_Station
West_Station East_Station South_Busport
South_Busport West_Station East_Station
The first word on each line provides a station name, and all following words are the names of neighbouring stations. In the above example, all links are bidirectional. Now, the shellscript assignports.sh (which will probably download when you click on the link), will produce a new shellscript with unused TCP and UDP ports assigned for each command. Running:
shell> ./assignports.sh adjacency startstations.sh
will produce the shellscript named startstations.sh
./station North_Terminus 4001 4002 4004 &
./station East_Station 4003 4004 4002 4008 4006 &
./station West_Station 4005 4006 4004 4008 &
./station South_Busport 4007 4008 4006 4004 &
Now, with all commands to start each server in a single shellscript, we can use makeform.sh (it will probably download when you click on the link), to find the station names and TCP ports in the starting script, and produce a webpage that can be used to query each server. Running:
shell> ./makeform.sh startstations.sh myform.html
Station servers communicate with each other using UDP/IP datagrams. Servers do not establish or maintain connections between each other, and send datagrams on-demand. Stations know the ports on which their neighbouring stations are expecting datagrams, but not the ports of other stations. Datagrams will be used to transmit both queries and replies between neighbouring stations.
The contents of each UDP datagram (in its payload) will need to be formatted so that they can be unambiguously understood by its receiver. Their format does not need to match that of the HTTP or HTML protocols (that would be overkill for our requirements). However, you will be defining a protocol understood by your stations.
Be warned that, while two Java programs can exchange Java objects across a network, programs written in other programming languages will not be able to parse/understand Java objects.
Finally. The shellscript buildtransperthtimetables.sh (it will probably download when you click on the link), reads the Transperth files and reduces the information to a set of more manageable timetable files, suitable for this project. Read the following points carefully: