瀏覽代碼

Main functionality working.

Joshua Rutschmann 7 年之前
父節點
當前提交
5e7008bb77
共有 3 個文件被更改,包括 79 次插入307 次删除
  1. 3
    3
      hw9/task2/src/cli.yml
  2. 47
    4
      hw9/task2/src/main.rs
  3. 29
    300
      hw9/task2/srv-commands/src/lib.rs

+ 3
- 3
hw9/task2/src/cli.yml 查看文件

@@ -13,8 +13,8 @@ args:
13 13
         long: "address"
14 14
         value_name: "ADDRESS"
15 15
         help: "the address, where the server can be reached (127.0.0.1 is default)"
16
-        takes_value: true 
17
-	required: false
16
+        takes_value: true
17
+        required: false
18 18
 
19 19
     - port:
20 20
         short: "p"
@@ -22,7 +22,7 @@ args:
22 22
         value_name: "PORT"
23 23
         help: "the port, where the server can be reached (7878 is default)"
24 24
         takes_value: true
25
-	required: true
25
+        required: true
26 26
 
27 27
 subcommands:
28 28
     - test:

+ 47
- 4
hw9/task2/src/main.rs 查看文件

@@ -1,11 +1,54 @@
1 1
 #[macro_use]
2 2
 extern crate clap;
3
+extern crate srv_commands;
3 4
 
4 5
 use clap::App;
6
+use std::io::{BufReader, BufRead};
7
+use std::collections::VecDeque;
5 8
 use std::net::{TcpListener, TcpStream};
9
+use srv_commands::Command;
6 10
 
7 11
 fn handle_client(stream: TcpStream) {
8
-    // ...
12
+    println!("New Client connected");
13
+    let mut orders:VecDeque<Command> = VecDeque::new(); 
14
+    let mut reader = BufReader::new(stream);
15
+    loop {
16
+        let mut line = String::new();
17
+        match reader.read_line(&mut line) {
18
+            Ok(n) => {
19
+                if n == 0 {
20
+                    break;
21
+                }
22
+
23
+                let cmd = srv_commands::parse(&line); 
24
+                println!("Command: {:?}", cmd);
25
+                
26
+                match cmd {
27
+                    Command::Stage(_) => {
28
+                        orders.push_front(cmd);
29
+                    }
30
+                    Command::Retrieve => {
31
+                        if orders.is_empty() {
32
+                            println!("No order on stage!");
33
+                        } else {
34
+                            println!("{:?}", orders.pop_front());
35
+                        }
36
+                    }
37
+                    Command::Control(ref control_string) => {
38
+                        println!("Received Control: {}", control_string);
39
+                    }
40
+                    Command::ParseError(_) => {
41
+                        println!("Error occurred: {:?}", cmd);
42
+                    }
43
+                }
44
+            },
45
+            _ => {
46
+                break;
47
+            },
48
+        }
49
+    }
50
+
51
+    println!("Client diconnected");
9 52
 }
10 53
 
11 54
 pub fn main() {
@@ -30,15 +73,15 @@ pub fn main() {
30 73
     }
31 74
 
32 75
     let host = format!("{}:{}", address, port);
76
+
33 77
     match TcpListener::bind(host) {
34 78
         Ok(listener) => {
35
-            // accept connections and process them serially
36 79
             for stream in listener.incoming() {
37 80
                 match stream {
38 81
                     Ok(stream) => {
39
-                        println!("new client!");
82
+						handle_client(stream);
40 83
                     }
41
-                    Err(e) => { /* connection failed */ }
84
+                    Err(_) => { /* connection failed */ }
42 85
                 }
43 86
             }
44 87
         }

+ 29
- 300
hw9/task2/srv-commands/src/lib.rs 查看文件

@@ -1,308 +1,37 @@
1
-extern crate sha2;
2
-extern crate time;
3
-
4
-#[cfg(feature = "SHA2")]
5
-use self::sha2::Sha256;
6
-use std::thread;
7
-use std::sync::Arc;
8
-use std::sync::atomic::AtomicBool;
9
-use std::sync::atomic::Ordering::Relaxed;
10
-use std::sync::mpsc::{Sender, channel};
11
-use time::{Duration, get_time};
12
-
13
-
14
-pub struct Sha256;
15
-
16
-pub trait Hasher {
17
-    type Output: HashResult;
18
-    fn hash(input: &[u8]) -> Self::Output;
19
-}
20
-
21
-pub trait HashResult {
22
-    /// Get the output in hex notation.
23
-    fn hex(&self) -> String;
24
-    /// Size of the output in bytes.
25
-    fn size() -> usize;
26
-}
27
-
28
-impl Hasher for Sha256 {
29
-    type Output = [u8; 32];
30
-
31
-    fn hash(input: &[u8]) -> Self::Output {
32
-        use self::sha2::*;
33
-        let mut tmp = Sha256::new();
34
-        tmp.input(input);
35
-        let r = tmp.result().as_slice().to_vec();
36
-        [
37
-            r[0],
38
-            r[1],
39
-            r[2],
40
-            r[3],
41
-            r[4],
42
-            r[5],
43
-            r[6],
44
-            r[7],
45
-            r[8],
46
-            r[9],
47
-            r[10],
48
-            r[11],
49
-            r[12],
50
-            r[13],
51
-            r[14],
52
-            r[15],
53
-            r[16],
54
-            r[17],
55
-            r[18],
56
-            r[19],
57
-            r[20],
58
-            r[21],
59
-            r[22],
60
-            r[23],
61
-            r[24],
62
-            r[25],
63
-            r[26],
64
-            r[27],
65
-            r[28],
66
-            r[29],
67
-            r[30],
68
-            r[31],
69
-        ]
70
-    }
71
-}
72
-
73
-impl HashResult for [u8; 32] {
74
-    fn hex(&self) -> String {
75
-        const HEX: [char; 16] = [
76
-            '0',
77
-            '1',
78
-            '2',
79
-            '3',
80
-            '4',
81
-            '5',
82
-            '6',
83
-            '7',
84
-            '8',
85
-            '9',
86
-            'a',
87
-            'b',
88
-            'c',
89
-            'd',
90
-            'e',
91
-            'f',
92
-        ];
93
-        let mut tmp = String::with_capacity(32 * 2);
94
-        for byte in self.iter() {
95
-            tmp.push(HEX[*byte as usize / 16]);
96
-            tmp.push(HEX[*byte as usize % 16]);
1
+pub fn parse(message: &str) -> Command {
2
+    let m: String = String::from(message);
3
+    let mut line = m.lines();
4
+    match line.next() {
5
+        Some(x) => {
6
+            let mut str = x.split_whitespace();
7
+            match str.next() {
8
+                Some("STAGE") => {
9
+                    let msg = m[6..].trim_left();
10
+                    Command::Stage(msg.to_string())
11
+                }
12
+                Some("CONTROL") => {
13
+                    let cmd = m[8..].trim_left();
14
+                    Command::Control(cmd.to_string())
15
+                }
16
+                Some("RETRIEVE") => Command::Retrieve,
17
+                Some(_) => Command::ParseError(ErrorType::UnknownCommand),
18
+                None => Command::ParseError(ErrorType::EmptyString),
19
+            }
97 20
         }
98
-        tmp
99
-    }
100
-
101
-    fn size() -> usize {
102
-        32
21
+        None => Command::ParseError(ErrorType::EmptyString),
103 22
     }
104 23
 }
105 24
 
106 25
 #[derive(Debug, PartialEq)]
107
-pub struct Solution {
108
-    pub number: usize,
109
-    pub hash: String,
26
+pub enum Command {
27
+    Stage(String),
28
+    Control(String),
29
+    Retrieve,
30
+    ParseError(ErrorType),
110 31
 }
111 32
 
112
-/// Überprüft ob *base* und *number* auf einen Hash abbilden,
113
-/// der mit der übergebenen *difficulty* übereinstimmt.
114
-/// Falls ja, kommt eine `Solution` in der Option mit den Ergebnissen zurück.
115
-/// Falls nein, steht None im Optional
116
-pub fn verify_product(base: usize, number: usize, difficulty: &String) -> Option<Solution> {
117
-    let sol = base * number;
118
-    let input = sol.to_string();
119
-    let bytes = input.as_bytes();
120
-
121
-    let hash = Sha256::hash(bytes).hex();
122
-
123
-    if hash.ends_with(difficulty) {
124
-        return Some(Solution {
125
-            number: number,
126
-            hash: hash,
127
-        });
128
-    }
129
-
130
-    None
131
-}
132
-
133
-/// Sucht nach einem Hash für die angegebene Basis und die Schwierigkeit.
134
-/// Wenn `total` > 1 ist, dann hat jeder Aufruf mit einem anderen `start`-Wert (von 0 - total)
135
-/// eine disjunkte Zahlenmenge für die Suche zur Auswahl.
136
-fn search_hash(
137
-    hash: &String,
138
-    base: usize,
139
-    start: usize,
140
-    total: usize,
141
-    sync: bool,
142
-    found: Arc<AtomicBool>,
143
-    special: usize,
144
-    solution_tx: Sender<Solution>,
145
-    timing_tx: Sender<(Duration, usize)>,
146
-    measure: bool,
147
-) {
148
-    let max = <usize>::max_value();
149
-    let mut n = start;
150
-
151
-    let thread_start = get_time();
152
-    while n < max {
153
-
154
-        // Der special Parameter begrenzt die Anzahl der load()-Aufrufe auf jeden n.ten Loop.
155
-        if n % special == 0 && found.load(Relaxed) {
156
-            // Anderer Thread hat eine Lösung gefunden (sync ist aktiviert). Beende Suche.
157
-            break;
158
-        }
159
-
160
-        if let Some(solution) = verify_product(base, n, hash) {
161
-            if sync {
162
-                found.store(true, Relaxed);
163
-            }
164
-            // Sende gefundene Solution an den Consumer.
165
-            let _ = solution_tx.send(solution);
166
-            // Beende Suche.
167
-            break;
168
-        }
169
-        n += total;
170
-    }
171
-
172
-    // Falls measure aktiviert ist Sende Zeitdauer und Anzahl Loops an den Consumer.
173
-    if measure {
174
-        let thread_end = get_time();
175
-        let _ = timing_tx.send((thread_end - thread_start, (n / total)));
176
-    }
177
-}
178
-
179
-/// Teilt, wenn nötig, die Suche nach dem Hash auf mehrere Threads auf.
180
-/// Gibt ggf. die Solution (für die Tests) zurück.
181
-pub fn search_with_threads(
182
-    threads: usize,
183
-    diff_string: String,
184
-    with_base: usize,
185
-    time_measurement: bool,
186
-    verbosity: u64,
187
-    sync: Option<usize>,
188
-    wait: bool,
189
-) -> Option<Solution> {
190
-
191
-    let diff = Arc::new(diff_string);
192
-    let mut children = vec![];
193
-    let mut solution = None;
194
-
195
-    let (solution_tx, solution_rx) = channel();
196
-    let (timing_tx, timing_rx) = channel();
197
-
198
-    let found = Arc::new(AtomicBool::new(false));
199
-    let m = time_measurement && verbosity > 0;
200
-
201
-    let total_start = get_time();
202
-    if threads > 1 {
203
-
204
-        if verbosity > 0 {
205
-            println!("Searching with {} threads", threads);
206
-        }
207
-
208
-        // Erstellt Anzahl angeforderter Threads.
209
-        // Klont für jeden Thread die Referenz auf die gemeinsamen Variablen.
210
-        for i in 0..threads {
211
-            let diff = diff.clone();
212
-            let solution_tx = solution_tx.clone();
213
-            let timing_tx = timing_tx.clone();
214
-            let found = found.clone();
215
-
216
-            children.push(thread::spawn(move || {
217
-
218
-                // Suche in jedem der Threads.
219
-                search_hash(
220
-                    &diff,
221
-                    with_base,
222
-                    i,
223
-                    threads,
224
-                    sync.is_some(),
225
-                    found,
226
-                    sync.unwrap_or(1),
227
-                    solution_tx,
228
-                    timing_tx,
229
-                    m,
230
-                );
231
-
232
-                if verbosity > 1 {
233
-                    println!("[DEBUG] Thread {} exited", i);
234
-                }
235
-            }));
236
-        }
237
-    } else {
238
-        // Suche auf dem Main-Thread.
239
-        search_hash(
240
-            &diff,
241
-            with_base,
242
-            0,
243
-            1,
244
-            sync.is_some(),
245
-            found,
246
-            sync.unwrap_or(1),
247
-            solution_tx,
248
-            timing_tx,
249
-            m,
250
-        );
251
-
252
-        if verbosity > 1 {
253
-            println!("[DEBUG] Finished search on main thread.");
254
-        }
255
-    }
256
-
257
-    // Empfängt die Lösung von einem der Producer.
258
-    match solution_rx.recv() {
259
-        Ok(sol) => {
260
-            solution = Some(Solution {
261
-                number: sol.number,
262
-                hash: sol.hash.clone(),
263
-            });
264
-            let total_end = get_time();
265
-            println!("Number: {} --> hash: {}", sol.number, sol.hash);
266
-            if time_measurement && verbosity == 0 {
267
-                let diff = total_end - total_start;
268
-                let s = diff.num_seconds();
269
-                let ms = diff.num_milliseconds();
270
-                let us = diff.num_microseconds().unwrap_or(ms * 1000);
271
-                println!("(Duration {}s / {}ms / {}us)", s, ms, us);
272
-            }
273
-        }
274
-        Err(_) => {}
275
-    }
276
-
277
-    let mut sum_loops = 0usize;
278
-    let mut sum_time: Duration = Duration::zero();
279
-
280
-    for child in children {
281
-
282
-        if time_measurement && verbosity > 0 {
283
-            // Warte auf Zeitstatistik-Nachricht von jedem Thread auf dem zweiten MPSC Channel.
284
-            if let Ok(stats) = timing_rx.recv() {
285
-                // Addiere Werte dieses threads zu der Summe.
286
-                sum_time = sum_time + stats.0;
287
-                sum_loops += stats.1;
288
-            }
289
-        }
290
-
291
-        // Falls *wait* wahr ist, warte auf aktuellen thread (child)
292
-        if wait {
293
-            let _ = child.join();
294
-        }
295
-    }
296
-
297
-    // Gebe die Gesamtergebnisse der Threads aus.
298
-    if time_measurement && verbosity > 0 {
299
-        println!("Sum Loops in Producers:       {}", sum_loops);
300
-        let s = sum_time.num_seconds();
301
-        let ms = sum_time.num_milliseconds();
302
-        let us = sum_time.num_microseconds().unwrap_or(ms * 1000);
303
-        println!("Sum Duration in Producers:    {}s / {}ms / {}us", s, ms, us);
304
-    }
305
-
306
-    // Gebe die Option einer Solution zurück.
307
-    solution
33
+#[derive(Debug, PartialEq)]
34
+pub enum ErrorType {
35
+    UnknownCommand,
36
+    EmptyString,
308 37
 }

Loading…
取消
儲存