|
1 |
| -# Protocol |
| 1 | +#### CITS3002 - Networks Project |
2 | 2 |
|
3 |
| -For our client-server protocol, communications are undertaken through used of a fixed size, 64 byte, UTF-8 header. This header is sent between the client and server in order to describe the manner in which communications will proceed. |
| 3 | +*Jamie McCullough **22238418** and Cormac Sharkey **22983427*** |
4 | 4 |
|
5 |
| -The header is comprised of up to three components: (1) communication code; (2) option flags; and (3) length of the message to be sent (called the payload). The payload is then sent to the recipient, with it's data expected to match the header-described attributes. Payloads can be of variable length, which is why their length is indicated by the header. |
| 5 | +--- |
6 | 6 |
|
7 |
| -## Communication Codes |
| 7 | +For our client-server protocol, communications are undertaken through used of a fixed size, 64 byte, UTF-8 header. The header is comprised of up to three components: communication code; option flags; and length of the message to be sent (payload). Payload is then sent to the recipient, with it's data expected to match the header-described attributes. |
8 | 8 |
|
9 |
| -These are the first two bytes of the header, called the communication code, or `code`. The code is one of a set of preset values, each indicating the manner in which communications should proceed. These values are as follows: |
| 9 | +#### Communication Codes |
10 | 10 |
|
11 |
| -#### `DISCONN_MSG` (!D) |
| 11 | +##### `DISCONN_MSG` (!D) |
12 | 12 |
|
13 |
| -- **Client**: sends to server once it has finished with it. |
14 |
| -- **Server**: cleans up data structures for client |
| 13 | +**Client**: Sends to server once it has finished with it. |
| 14 | +**Server**: Cleans up data structures for client. |
15 | 15 |
|
16 |
| -#### `COMMAND_MSG` (!C) |
| 16 | +##### `COMMAND_MSG` (!C) |
17 | 17 |
|
18 |
| -- **Client**: Sends this with a payload of command to execute. |
19 |
| -- **Server**: Executes the payload from this packet, and captures exit state, stdout, stderr, and any generated files, and passes it off to the client |
| 18 | +**Client**: Sends this with a payload of command to execute. |
| 19 | +**Server**: Executes payload, captures exit state, stdout, stderr, and generated files, passing them to client. |
20 | 20 |
|
21 |
| -#### `REQUEST_MSG` (!R) |
| 21 | +##### `REQUEST_MSG` (!R) |
22 | 22 |
|
23 |
| -- **Client**: Sends this to indicate to the server that it will need to receive files |
24 |
| -- **Server**: Prepares to receive files from the client |
| 23 | +**Client**: Sends this to indicate to the server that it will need to receive files. |
| 24 | +**Server**: Prepares to receive files from the client. |
25 | 25 |
|
26 |
| -#### `SUCCEED_RSP` (!S) |
| 26 | +##### `SUCCEED_RSP` (!S) |
27 | 27 |
|
28 |
| -- **Client**: Indicates success, should keep processing the packet and rakefile. Exit code equals 0 since otherwise it would be a FAILURE_RSP packet |
29 |
| -- **Server**: Sends this to indicate execution was successful (exit code == 0) |
| 28 | +**Client**: Indicates success, keeps processing packet and Rakefile. |
| 29 | +**Server**: Sent to indicate execution was successful (exit code == 0). |
30 | 30 |
|
31 |
| -#### `FAILURE_RSP` (!F) |
| 31 | +##### `FAILURE_RSP` (!F) |
32 | 32 |
|
33 |
| -- **Client**: Indicates failure, receive two packets, one containing the stderr and one containing the exit code. |
34 |
| -- **Server**: Sends this to indicate execution was unsuccessful. Detect based on exit code. |
| 33 | +**Client**: Indicates failure, receive two packets, one containing the stderr and one containing the exit code. |
| 34 | +**Server**: Sends this to indicate execution was unsuccessful. Detect based on exit code. |
35 | 35 |
|
36 |
| -#### `EXECUTE_GET` (!E) |
| 36 | +**`EXECUTE_GET` (!E)** |
37 | 37 |
|
38 |
| -- **Client**: Sends this to get current amount of requests server is servicing |
39 |
| -- **Server**: Sends active thread count to client, effectively the load of the server. |
| 38 | +**Client**: Sends this to get current amount of requests server is servicing |
| 39 | +**Server**: Sends active thread count to client, effectively the load of the server. |
40 | 40 |
|
| 41 | +#### Option Flags |
41 | 42 |
|
| 43 | +**`STDOUTP` (S)**: Set if the packet contains standard output |
| 44 | +**`INCFILE` (I):** Set if files to be sent back to client for it to prepare to receive a filestream. |
| 45 | +**`FILETRN` (F):** Set only on filestream packets |
42 | 46 |
|
43 |
| -## Option Flags |
| 47 | +#### Message Length |
44 | 48 |
|
45 |
| -The next three bytes are "options", only used on successful execution responses. These are positionally sensitive, and are either set, or unset(replaced with a space): |
| 49 | +Last bytes indicate the length of the payload. This value is padded out to be the length of the remaining bytes in the header. i.e. Message sent with code of `!E` would be padded by 62 bytes of white space, bringing the length to 64 bytes total. |
46 | 50 |
|
47 |
| -* STDOUTP = "S" |
48 |
| -* INCFILE = "I" |
49 |
| -* FILETRN = "F" |
50 |
| -* S is set if the packet contains standard output |
51 |
| -* I is set if output files are to be sent back to the client, and for it to prepare to receive a filestream |
52 |
| -* F is set only on filestream packets |
| 51 | +#### Filestream Protocol |
53 | 52 |
|
54 |
| -Finally, the next bytes indicate the length of the payload, and the rest of the header is padded out to 64 bytes total with spaces. |
| 53 | +Filestreams are multiple files to sent and received between the client and server. Each consists of a metadata packet, packets for each filename, filesize, and for transfer confirmation. Filestreams use these codes to replace the first two bytes of "options", with last byte of options, set to` F` to indicate it is a filestream. Meta packets are have all three options set. i.e `!S` + `SIF` + `length` + `padding` |
55 | 54 |
|
56 |
| -## Filestream protocol |
| 55 | + FILENAME = "!N" FILETRAN = "!T" FILESIZE = "!Z" |
| 56 | +**Header**: `!S!NF7[57 spaces]` **Payload**: `Dog.txt` |
57 | 57 |
|
58 |
| -Filestreams are just multiple files to be sent and received by a client and server. Each filestream consists of a metadata packet, and for each file, packets for filename, filesize, and for transfer confirmation. Filestreams use one of these codes in replacement of the first two bytes of the "options", with the last byte of options set to F to indicate that it is a filestream packet. The metadata packet is distinguished by having all three normal options set, e.g `!S` + `SIF` + payload length + padding |
59 |
| - |
60 |
| - FILENAME = "!N" |
61 |
| - FILETRAN = "!T" |
62 |
| - FILESIZE = "!Z" |
63 |
| -As an example, the client receiving a filestream might ask for the filename of one of the files its receiving by sending off (padded to 64 bytes)`!N`, and get this back: |
64 |
| - Header: `!S!NF7[57 spaces]` |
65 |
| - Payload: `Dog.txt` |
66 |
| - |
67 |
| -An example exchange between client and server, with the client sending a filestream of dog.txt(34 bytes) and feline.txt(88 bytes) to the server, as requirements. Note that all non file traffic is padded to 64 bytes with spaces, which is not shown here. |
| 58 | +**Example:** `dog.txt` and `feline.txt`. |
68 | 59 |
|
69 | 60 | ```
|
70 | 61 | |--------!R--------->| Indicate requirements
|
71 | 62 | |------!SSIF2------->| Client sends metadata packet showing 2 files to be sent
|
72 |
| -
|
73 | 63 | |<-------!N----------| Server asks for name of first file
|
74 |
| -|------!S!N7-------->| Client sends 64 byte header indicating 7 byte filename payload |
75 |
| -|------dog.txt------>| Client sents payload of filename |
| 64 | +|------!S!N7-------->| Client sends header indicating 7 byte filename |
| 65 | +|------dog.txt------>| Client sends payload of filename |
76 | 66 | |<-------!Z----------| Server asks for filesize of first file
|
77 |
| -|------!S!Z2-------->| Client sends 64 byte header indicating 2 byte file size payload |
78 |
| -|--------34--------->| Client sents payload of file size |
| 67 | +|------!S!Z2-------->| Client sends header indicating 2 byte file size |
| 68 | +|--------34--------->| Client sends payload of file size |
79 | 69 | |<-------!T----------| Server requests transmission to start
|
80 |
| -|-The dog or domes..>| Client begins transfer of file. Server receives based on filesize and saves to file based on received filename |
81 |
| -
|
82 |
| -|<-------!N----------| Server asks for name of second file |
83 |
| -|------!S!N10------->| Client sends 64 byte header indicating 10 byte filename payload |
84 |
| -|------feline.txt--->| Client sents payload of filename |
85 |
| -|<-------!Z----------| Server asks for filesize of second file |
86 |
| -|------!S!Z2-------->| Client sends 64 byte header indicating 2 byte file size payload |
87 |
| -|--------88--------->| Client sents payload of file size |
88 |
| -|<-------!T----------| Server requests transmission to start |
89 |
| -|-Feline may refer..>| Client begins transfer of file. Server receives based on filesize and saves to file based on received filename |
90 |
| -
|
| 70 | +|-The dog or domes..>| Client begins transfer of file. |
| 71 | +Server receives based on filesize and saves to file based on received filename |
| 72 | +[Repeat steps 3 onward for feline.txt] |
91 | 73 | ```
|
92 | 74 |
|
93 |
| -# Execution Sequence |
| 75 | +#### Execution Walkthrough |
94 | 76 |
|
95 |
| -Test case: One client, two servers |
96 |
| - |
97 |
| -```PORT |
| 77 | +```makefile |
98 | 78 | HOSTS = host1 host2
|
99 | 79 |
|
100 | 80 | actionset1:
|
101 | 81 | remote-cc -c func1.c
|
102 | 82 | requires func1.c
|
103 |
| - remote-cc -c func2.c |
104 |
| - requires func2.c |
| 83 | +[...] |
| 84 | +``` |
105 | 85 |
|
106 |
| -actionset2: |
107 |
| - remote-cc -c program2.c |
108 |
| - requires program2.c |
| 86 | +1. Client parses the rake file then looks at the actionset. |
109 | 87 |
|
110 |
| -actionset3: |
111 |
| - remote-cc -o program2 program2.o func1.o func2.o |
112 |
| - requires program2.o func1.o func2.o |
113 |
| -``` |
| 88 | +2. `remote-cc -c func1.c requires func1.c` |
114 | 89 |
|
115 |
| -* Client parses the rake file successfully |
116 |
| -* Client looks at the first actionset, and for each action: |
117 |
| - - `remote-cc -c func1.c requires func1.c` |
118 |
| - - Polls host1 and host2 by sending `!E`(plus payload length and padding). |
119 |
| - - Receives from host1: |
120 |
| - - Header: `!E1[padding]` |
121 |
| - - Payload: `0` |
122 |
| - - Receives from host2 |
123 |
| - - Header: `!E1[padding]` |
124 |
| - - Payload: `0` |
125 |
| - - Neither are busy, so picks host1. |
126 |
| - - Sees func1.c is required for action |
127 |
| - - Sends `!R`(plus payload length and padding) to server, then sends filestream of func1.c |
128 |
| - - Sends `!C`(plus payload length and padding) to server, with payload `remote-cc -c func1.c` |
129 |
| - - Server executes command, and detects output to send back |
130 |
| - - Client doesn''t wait for response, but adds host1's socket to a watchlist, and increments the count of commands sent by one |
131 |
| - - `remote-cc -c func2.c requires func2.c` |
132 |
| - + Polls host1 and 2. |
133 |
| - - Receives from host1: |
134 |
| - - Header: `!E1[padding]` |
135 |
| - - Payload: `1` |
136 |
| - - Receives from host2 |
137 |
| - - Header: `!E1[padding]` |
138 |
| - - Payload: `0` |
139 |
| - + 1 has one more active thread than 2 (it is currently compiling our first action), so we pick 2 |
140 |
| - + Sees func2.c is required for action |
141 |
| - - Sends `!R` (plus payload length and padding) to server, then sends filestream of func2.c |
142 |
| - - Sends `!C` (plus payload length and padding) to server, with payload `remote-cc -c func2.c |
143 |
| - - Server executes command, and detects output to send back |
144 |
| - - Client doesn''t wait for response, but adds host2's socket to a watchlist, and increments the count of commands sent by one |
145 |
| - * Until commands sent = 0 |
146 |
| - - select() our watchlist, see 1 is ready |
147 |
| - + Get header |
148 |
| - + `!SSI 0[padding]` |
149 |
| - + Get payload |
150 |
| - * Nothing, no stdout |
151 |
| - + I is set, so we pass the socket off to the filestream handler and receive func1.o |
152 |
| - - select() our watchlist, see 2 is ready |
153 |
| - + Get header |
154 |
| - + `!SSI 0[padding]` |
155 |
| - + Get payload |
156 |
| - * Nothing, no stdout |
157 |
| - + I is set, so we pass the socket off to the filestream handler and receive func2.o |
158 |
| - |
159 |
| - Repeat this process for actionsets 2 and 3, unless one of these actions failed. If one did, terminate. |
160 |
| - |
161 |
| -# Remote compilation performace |
| 90 | + - Polls host1 and host2 by sending `!E`(plus payload length). |
162 | 91 |
|
163 |
| -Remote compilation performs better under these conditions: |
| 92 | + - Receives from host1: `!E1[padding]` and `0` |
164 | 93 |
|
165 |
| -* The server has a faster compilation time than the client. (Perhaps the client is a small, embedded device, and the server is a proper workstation) |
166 |
| -* This performance difference is larger than the performance penalty incurred by sending the files over a network. (If the network is slow enough, it can simply take more time to transfer requirements than any time saved by using a better CPU) |
| 94 | + - Receives from host2`!E1[padding]` and `0` |
167 | 95 |
|
168 |
| -Additional considerations include that large complex compilations can be spread across an arbitrary amount of servers, so a huge task which can be executed in parallel would perform better remotely than locally. |
| 96 | + - Neither busy, picks host1, sees `func1.c` is required for command |
| 97 | + |
| 98 | + - Sends `!R` + payload length, then sends filestream of `func1.c` |
| 99 | + |
| 100 | + - Sends `!C` + payload length to server, with payload `remote-cc -c func1.c` |
| 101 | + |
| 102 | + - Server executes command, detects output to send |
| 103 | + |
| 104 | + - Client doesn't wait, instead adds host1 socket to watchlist, incrementing command sent count. |
| 105 | + |
| 106 | +3. Until commands waiting = `0`, `select()` watchlist, see host 1 is ready: |
| 107 | + - Get header and payload `!SSI 0[padding]`and nothing (no stdout) |
| 108 | + - `I` set, so pass socket to filestream handler and receive `func1.o` |
| 109 | + |
| 110 | +4. Repeat this process for other actionsets (unless a command failed, then terminate). |
| 111 | + |
| 112 | +### Remote Compilation Performance |
| 113 | + |
| 114 | +Remote compilation performs better under these conditions: |
| 115 | +(1) The server has a faster compilation time than the client. Perhaps the client is a small, embedded device, and the server is a proper workstation. |
| 116 | +(2) Performance difference is larger than performance penalty incurred by sending over a network. If the network is slow, it can take more time to transfer requirements than that saved through a better CPU. |
| 117 | +(3) Large complex compilations can be spread across an arbitrary amount of servers, a huge task which can be executed in parallel would perform better remotely than locally. |
0 commit comments