fwefwefw commited on
Commit
76bf311
·
verified ·
1 Parent(s): ece0452

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +1012 -19
index.html CHANGED
@@ -1,19 +1,1012 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="ru">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>C# to Rust UDP Converter</title>
7
+ <link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css" rel="stylesheet" />
8
+ <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
9
+ <style>
10
+ * {
11
+ margin: 0;
12
+ padding: 0;
13
+ box-sizing: border-box;
14
+ }
15
+
16
+ :root {
17
+ --primary: #6366f1;
18
+ --primary-dark: #4f46e5;
19
+ --secondary: #f97316;
20
+ --bg-dark: #0f172a;
21
+ --bg-card: #1e293b;
22
+ --bg-code: #0d1117;
23
+ --text-primary: #f1f5f9;
24
+ --text-secondary: #94a3b8;
25
+ --border: #334155;
26
+ --success: #10b981;
27
+ --error: #ef4444;
28
+ }
29
+
30
+ body {
31
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
32
+ background: linear-gradient(135deg, var(--bg-dark) 0%, #1a1f3a 100%);
33
+ color: var(--text-primary);
34
+ min-height: 100vh;
35
+ line-height: 1.6;
36
+ }
37
+
38
+ header {
39
+ background: rgba(30, 41, 59, 0.8);
40
+ backdrop-filter: blur(10px);
41
+ border-bottom: 1px solid var(--border);
42
+ padding: 1.5rem 2rem;
43
+ position: sticky;
44
+ top: 0;
45
+ z-index: 100;
46
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
47
+ }
48
+
49
+ .header-content {
50
+ max-width: 1400px;
51
+ margin: 0 auto;
52
+ display: flex;
53
+ justify-content: space-between;
54
+ align-items: center;
55
+ flex-wrap: wrap;
56
+ gap: 1rem;
57
+ }
58
+
59
+ .logo {
60
+ display: flex;
61
+ align-items: center;
62
+ gap: 1rem;
63
+ font-size: 1.5rem;
64
+ font-weight: 700;
65
+ color: var(--text-primary);
66
+ }
67
+
68
+ .logo i {
69
+ color: var(--primary);
70
+ font-size: 2rem;
71
+ }
72
+
73
+ .nav-links {
74
+ display: flex;
75
+ gap: 2rem;
76
+ align-items: center;
77
+ }
78
+
79
+ .nav-links a {
80
+ color: var(--text-secondary);
81
+ text-decoration: none;
82
+ transition: color 0.3s;
83
+ font-weight: 500;
84
+ }
85
+
86
+ .nav-links a:hover {
87
+ color: var(--primary);
88
+ }
89
+
90
+ .brand-link {
91
+ color: var(--primary) !important;
92
+ font-weight: 600;
93
+ }
94
+
95
+ main {
96
+ max-width: 1400px;
97
+ margin: 2rem auto;
98
+ padding: 0 2rem;
99
+ }
100
+
101
+ .converter-section {
102
+ background: var(--bg-card);
103
+ border-radius: 1rem;
104
+ padding: 2rem;
105
+ margin-bottom: 2rem;
106
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
107
+ border: 1px solid var(--border);
108
+ }
109
+
110
+ .section-header {
111
+ display: flex;
112
+ justify-content: space-between;
113
+ align-items: center;
114
+ margin-bottom: 1.5rem;
115
+ flex-wrap: wrap;
116
+ gap: 1rem;
117
+ }
118
+
119
+ .section-title {
120
+ font-size: 1.75rem;
121
+ font-weight: 700;
122
+ display: flex;
123
+ align-items: center;
124
+ gap: 0.75rem;
125
+ }
126
+
127
+ .section-title i {
128
+ color: var(--primary);
129
+ }
130
+
131
+ .code-container {
132
+ display: grid;
133
+ grid-template-columns: 1fr;
134
+ gap: 2rem;
135
+ }
136
+
137
+ @media (min-width: 1024px) {
138
+ .code-container {
139
+ grid-template-columns: 1fr 1fr;
140
+ }
141
+ }
142
+
143
+ .code-block {
144
+ position: relative;
145
+ background: var(--bg-code);
146
+ border-radius: 0.75rem;
147
+ overflow: hidden;
148
+ border: 1px solid var(--border);
149
+ }
150
+
151
+ .code-header {
152
+ background: rgba(30, 41, 59, 0.8);
153
+ padding: 1rem 1.5rem;
154
+ display: flex;
155
+ justify-content: space-between;
156
+ align-items: center;
157
+ border-bottom: 1px solid var(--border);
158
+ }
159
+
160
+ .language-tag {
161
+ display: flex;
162
+ align-items: center;
163
+ gap: 0.5rem;
164
+ font-weight: 600;
165
+ color: var(--text-primary);
166
+ }
167
+
168
+ .language-tag i {
169
+ font-size: 1.25rem;
170
+ }
171
+
172
+ .csharp-tag i {
173
+ color: #9b4f96;
174
+ }
175
+
176
+ .rust-tag i {
177
+ color: #ce422b;
178
+ }
179
+
180
+ .code-actions {
181
+ display: flex;
182
+ gap: 0.5rem;
183
+ }
184
+
185
+ .btn-icon {
186
+ background: rgba(99, 102, 241, 0.1);
187
+ border: 1px solid var(--primary);
188
+ color: var(--primary);
189
+ padding: 0.5rem 0.75rem;
190
+ border-radius: 0.5rem;
191
+ cursor: pointer;
192
+ transition: all 0.3s;
193
+ font-size: 0.875rem;
194
+ display: flex;
195
+ align-items: center;
196
+ gap: 0.5rem;
197
+ }
198
+
199
+ .btn-icon:hover {
200
+ background: var(--primary);
201
+ color: white;
202
+ transform: translateY(-2px);
203
+ box-shadow: 0 4px 6px -1px rgba(99, 102, 241, 0.3);
204
+ }
205
+
206
+ .code-content {
207
+ max-height: 500px;
208
+ overflow-y: auto;
209
+ padding: 1.5rem;
210
+ }
211
+
212
+ .code-content::-webkit-scrollbar {
213
+ width: 8px;
214
+ height: 8px;
215
+ }
216
+
217
+ .code-content::-webkit-scrollbar-track {
218
+ background: var(--bg-dark);
219
+ }
220
+
221
+ .code-content::-webkit-scrollbar-thumb {
222
+ background: var(--primary);
223
+ border-radius: 4px;
224
+ }
225
+
226
+ pre {
227
+ margin: 0;
228
+ font-family: 'Fira Code', 'Consolas', monospace;
229
+ font-size: 0.875rem;
230
+ line-height: 1.5;
231
+ }
232
+
233
+ code {
234
+ font-family: inherit;
235
+ }
236
+
237
+ .explanation-section {
238
+ background: linear-gradient(135deg, var(--bg-card) 0%, rgba(99, 102, 241, 0.05) 100%);
239
+ border-radius: 1rem;
240
+ padding: 2rem;
241
+ border: 1px solid var(--border);
242
+ }
243
+
244
+ .explanation-grid {
245
+ display: grid;
246
+ grid-template-columns: 1fr;
247
+ gap: 2rem;
248
+ margin-top: 1.5rem;
249
+ }
250
+
251
+ @media (min-width: 768px) {
252
+ .explanation-grid {
253
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
254
+ }
255
+ }
256
+
257
+ .explanation-card {
258
+ background: rgba(15, 23, 42, 0.5);
259
+ padding: 1.5rem;
260
+ border-radius: 0.75rem;
261
+ border: 1px solid var(--border);
262
+ transition: transform 0.3s, box-shadow 0.3s;
263
+ }
264
+
265
+ .explanation-card:hover {
266
+ transform: translateY(-4px);
267
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.2);
268
+ }
269
+
270
+ .card-icon {
271
+ width: 48px;
272
+ height: 48px;
273
+ background: rgba(99, 102, 241, 0.1);
274
+ border-radius: 0.75rem;
275
+ display: flex;
276
+ align-items: center;
277
+ justify-content: center;
278
+ margin-bottom: 1rem;
279
+ }
280
+
281
+ .card-icon i {
282
+ font-size: 1.5rem;
283
+ color: var(--primary);
284
+ }
285
+
286
+ .card-title {
287
+ font-size: 1.125rem;
288
+ font-weight: 600;
289
+ margin-bottom: 0.75rem;
290
+ color: var(--text-primary);
291
+ }
292
+
293
+ .card-text {
294
+ color: var(--text-secondary);
295
+ font-size: 0.875rem;
296
+ line-height: 1.6;
297
+ }
298
+
299
+ .features-grid {
300
+ display: grid;
301
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
302
+ gap: 1.5rem;
303
+ margin-top: 2rem;
304
+ }
305
+
306
+ .feature-item {
307
+ display: flex;
308
+ align-items: center;
309
+ gap: 1rem;
310
+ padding: 1rem;
311
+ background: rgba(99, 102, 241, 0.05);
312
+ border-radius: 0.5rem;
313
+ border: 1px solid rgba(99, 102, 241, 0.2);
314
+ }
315
+
316
+ .feature-item i {
317
+ color: var(--success);
318
+ font-size: 1.25rem;
319
+ }
320
+
321
+ .toast {
322
+ position: fixed;
323
+ bottom: 2rem;
324
+ right: 2rem;
325
+ background: var(--success);
326
+ color: white;
327
+ padding: 1rem 1.5rem;
328
+ border-radius: 0.5rem;
329
+ display: flex;
330
+ align-items: center;
331
+ gap: 0.75rem;
332
+ transform: translateX(400px);
333
+ transition: transform 0.3s;
334
+ z-index: 1000;
335
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.3);
336
+ }
337
+
338
+ .toast.show {
339
+ transform: translateX(0);
340
+ }
341
+
342
+ .tabs {
343
+ display: flex;
344
+ gap: 0.5rem;
345
+ margin-bottom: 1.5rem;
346
+ border-bottom: 1px solid var(--border);
347
+ }
348
+
349
+ .tab {
350
+ background: transparent;
351
+ border: none;
352
+ color: var(--text-secondary);
353
+ padding: 0.75rem 1.5rem;
354
+ cursor: pointer;
355
+ transition: all 0.3s;
356
+ font-weight: 500;
357
+ position: relative;
358
+ }
359
+
360
+ .tab:hover {
361
+ color: var(--text-primary);
362
+ }
363
+
364
+ .tab.active {
365
+ color: var(--primary);
366
+ }
367
+
368
+ .tab.active::after {
369
+ content: '';
370
+ position: absolute;
371
+ bottom: -1px;
372
+ left: 0;
373
+ right: 0;
374
+ height: 2px;
375
+ background: var(--primary);
376
+ }
377
+
378
+ .tab-content {
379
+ display: none;
380
+ }
381
+
382
+ .tab-content.active {
383
+ display: block;
384
+ }
385
+
386
+ .dependencies {
387
+ background: rgba(249, 115, 22, 0.1);
388
+ border: 1px solid rgba(249, 115, 22, 0.3);
389
+ border-radius: 0.5rem;
390
+ padding: 1rem;
391
+ margin-top: 1rem;
392
+ }
393
+
394
+ .dependencies-title {
395
+ color: var(--secondary);
396
+ font-weight: 600;
397
+ margin-bottom: 0.5rem;
398
+ display: flex;
399
+ align-items: center;
400
+ gap: 0.5rem;
401
+ }
402
+
403
+ .dependencies-list {
404
+ font-family: 'Fira Code', monospace;
405
+ font-size: 0.875rem;
406
+ color: var(--text-secondary);
407
+ }
408
+
409
+ @keyframes fadeIn {
410
+ from {
411
+ opacity: 0;
412
+ transform: translateY(20px);
413
+ }
414
+ to {
415
+ opacity: 1;
416
+ transform: translateY(0);
417
+ }
418
+ }
419
+
420
+ .fade-in {
421
+ animation: fadeIn 0.5s ease-out;
422
+ }
423
+ </style>
424
+ </head>
425
+ <body>
426
+ <header>
427
+ <div class="header-content">
428
+ <div class="logo">
429
+ <i class="fas fa-code"></i>
430
+ <span>Code Converter</span>
431
+ </div>
432
+ <nav class="nav-links">
433
+ <a href="#converter">Конвертер</a>
434
+ <a href="#explanation">Объяснения</a>
435
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="brand-link">
436
+ <i class="fas fa-rocket"></i> Built with anycoder
437
+ </a>
438
+ </nav>
439
+ </div>
440
+ </header>
441
+
442
+ <main>
443
+ <section id="converter" class="converter-section fade-in">
444
+ <div class="section-header">
445
+ <h2 class="section-title">
446
+ <i class="fas fa-exchange-alt"></i>
447
+ Конвертация C# в Rust
448
+ </h2>
449
+ <button class="btn-icon" onclick="downloadRustCode()">
450
+ <i class="fas fa-download"></i> Скачать Rust код
451
+ </button>
452
+ </div>
453
+
454
+ <div class="tabs">
455
+ <button class="tab active" onclick="switchTab('server')">
456
+ <i class="fas fa-server"></i> UDP Сервер
457
+ </button>
458
+ <button class="tab" onclick="switchTab('client')">
459
+ <i class="fas fa-desktop"></i> UDP Клиент
460
+ </button>
461
+ <button class="tab" onclick="switchTab('complete')">
462
+ <i class="fas fa-file-code"></i> Полный код
463
+ </button>
464
+ </div>
465
+
466
+ <div id="server-tab" class="tab-content active">
467
+ <div class="code-container">
468
+ <div class="code-block">
469
+ <div class="code-header">
470
+ <span class="language-tag csharp-tag">
471
+ <i class="fab fa-microsoft"></i> C#
472
+ </span>
473
+ <div class="code-actions">
474
+ <button class="btn-icon" onclick="copyCode('csharp-server')">
475
+ <i class="fas fa-copy"></i> Копировать
476
+ </button>
477
+ </div>
478
+ </div>
479
+ <div class="code-content">
480
+ <pre><code class="language-csharp" id="csharp-server">int port_local = 11000;
481
+
482
+ UdpClient server_local = new UdpClient(port_local);
483
+ Console.WriteLine($"UDP сервер запущен на порту {port_local}...");
484
+
485
+ IPEndPoint remoteEP_local = new IPEndPoint(IPAddress.Any, 0);
486
+ CancellationTokenSource token_local = new CancellationTokenSource();
487
+
488
+ Task serverTask_local = Task.Run(() =>
489
+ {
490
+ while (token_local.IsCancellationRequested == false)
491
+ {
492
+ try
493
+ {
494
+ byte[] data = server_local.Receive(ref remoteEP_local);
495
+ server_local.Send(data, data.Length, remoteEP_local);
496
+
497
+ string message = Encoding.UTF8.GetString(data);
498
+ Console.WriteLine($"Получено от {remoteEP_local}: {message}");
499
+ }
500
+ catch (Exception ex)
501
+ {
502
+ Log.ошибка(ex, "UDP serverTask");
503
+ }
504
+ }
505
+ });</code></pre>
506
+ </div>
507
+ </div>
508
+
509
+ <div class="code-block">
510
+ <div class="code-header">
511
+ <span class="language-tag rust-tag">
512
+ <i class="fab fa-rust"></i> Rust
513
+ </span>
514
+ <div class="code-actions">
515
+ <button class="btn-icon" onclick="copyCode('rust-server')">
516
+ <i class="fas fa-copy"></i> Копировать
517
+ </button>
518
+ </div>
519
+ </div>
520
+ <div class="code-content">
521
+ <pre><code class="language-rust" id="rust-server">use std::net::{UdpSocket, Ipv4Addr, SocketAddr};
522
+ use std::thread;
523
+ use std::sync::Arc;
524
+ use std::sync::atomic::{AtomicBool, Ordering};
525
+
526
+ const PORT: u16 = 11000;
527
+
528
+ pub fn start_udp_server() -> Arc&lt;AtomicBool&gt; {
529
+ let socket = UdpSocket::bind(("0.0.0.0", PORT))
530
+ .expect("Не удалось привязать сокет");
531
+
532
+ println!("UDP сервер запущен на порту {}", PORT);
533
+
534
+ let running = Arc::new(AtomicBool::new(true));
535
+ let running_clone = running.clone();
536
+
537
+ thread::spawn(move || {
538
+ let mut buf = [0; 1024];
539
+
540
+ while running_clone.load(Ordering::Relaxed) {
541
+ match socket.recv_from(&mut buf) {
542
+ Ok((size, src)) => {
543
+ let data = &buf[..size];
544
+ let message = String::from_utf8_lossy(data);
545
+ println!("Получено от {}: {}", src, message);
546
+
547
+ // Отправляем эхо-ответ
548
+ if let Err(e) = socket.send_to(data, src) {
549
+ eprintln!("Ошибка отправки: {}", e);
550
+ }
551
+ }
552
+ Err(e) => {
553
+ eprintln!("Ошибка приёма: {}", e);
554
+ }
555
+ }
556
+ }
557
+ });
558
+
559
+ running
560
+ }</code></pre>
561
+ </div>
562
+ </div>
563
+ </div>
564
+ </div>
565
+
566
+ <div id="client-tab" class="tab-content">
567
+ <div class="code-container">
568
+ <div class="code-block">
569
+ <div class="code-header">
570
+ <span class="language-tag csharp-tag">
571
+ <i class="fab fa-microsoft"></i> C#
572
+ </span>
573
+ <div class="code-actions">
574
+ <button class="btn-icon" onclick="copyCode('csharp-client')">
575
+ <i class="fas fa-copy"></i> Копировать
576
+ </button>
577
+ </div>
578
+ </div>
579
+ <div class="code-content">
580
+ <pre><code class="language-csharp" id="csharp-client">UdpClient udp_client_local = new UdpClient();
581
+ Task clientTask_local = Task.Run(async () =>
582
+ {
583
+ try
584
+ {
585
+ IPEndPoint serverEP = new IPEndPoint(IPAddress.Any, 0);
586
+ int messageCounter = 1;
587
+
588
+ while (token_local.IsCancellationRequested == false)
589
+ {
590
+ string message = $"Сообщение {messageCounter}";
591
+ byte[] data = Encoding.UTF8.GetBytes(message);
592
+
593
+ long start_time = Stopwatch.GetTimestamp();
594
+ udp_client_local.Send(data, data.Length, "127.0.0.1", port_local);
595
+
596
+ byte[] receivedData = udp_client_local.Receive(ref serverEP);
597
+ TimeSpan rtt = Stopwatch.GetElapsedTime(start_time);
598
+
599
+ string response = Encoding.UTF8.GetString(receivedData);
600
+ Console.WriteLine($"Ответ от сервера: {response} | RTT: {rtt.TotalMilliseconds.ToString("F3")} ms | PING: {(rtt.TotalMilliseconds / 2).ToString("F3")} ms");
601
+
602
+ messageCounter++;
603
+ await Task.Delay(1000);
604
+ }
605
+ }
606
+ catch (Exception ex)
607
+ {
608
+ Log.ошибка(ex, "clientTask");
609
+ }
610
+ });</code></pre>
611
+ </div>
612
+ </div>
613
+
614
+ <div class="code-block">
615
+ <div class="code-header">
616
+ <span class="language-tag rust-tag">
617
+ <i class="fab fa-rust"></i> Rust
618
+ </span>
619
+ <div class="code-actions">
620
+ <button class="btn-icon" onclick="copyCode('rust-client')">
621
+ <i class="fas fa-copy"></i> Копировать
622
+ </button>
623
+ </div>
624
+ </div>
625
+ <div class="code-content">
626
+ <pre><code class="language-rust" id="rust-client">use std::net::UdpSocket;
627
+ use std::time::{Duration, Instant};
628
+ use std::thread;
629
+
630
+ pub async fn start_udp_client(running: Arc&lt;AtomicBool&gt;) {
631
+ let socket = UdpSocket::bind("0.0.0.0:0")
632
+ .expect("Не удалось создать клиентский сокет");
633
+
634
+ let server_addr: SocketAddr = ("127.0.0.1", PORT).into();
635
+ let mut message_counter = 1;
636
+
637
+ while running.load(Ordering::Relaxed) {
638
+ let message = format!("Сообщение {}", message_counter);
639
+ let data = message.as_bytes();
640
+
641
+ let start_time = Instant::now();
642
+
643
+ // Отправляем сообщение
644
+ if let Err(e) = socket.send_to(data, server_addr) {
645
+ eprintln!("Ошибка отправки: {}", e);
646
+ continue;
647
+ }
648
+
649
+ // Получаем ответ
650
+ let mut buf = [0; 1024];
651
+ match socket.recv_from(&mut buf) {
652
+ Ok((size, _)) => {
653
+ let rtt = start_time.elapsed();
654
+ let response = String::from_utf8_lossy(&buf[..size]);
655
+
656
+ println!("Ответ от сервера: {} | RTT: {:.3} ms | PING: {:.3} ms",
657
+ response,
658
+ rtt.as_millis(),
659
+ rtt.as_millis() as f64 / 2.0);
660
+ }
661
+ Err(e) => {
662
+ eprintln!("Ошибка приёма: {}", e);
663
+ }
664
+ }
665
+
666
+ message_counter += 1;
667
+ thread::sleep(Duration::from_millis(1000));
668
+ }
669
+ }</code></pre>
670
+ </div>
671
+ </div>
672
+ </div>
673
+ </div>
674
+
675
+ <div id="complete-tab" class="tab-content">
676
+ <div class="code-block">
677
+ <div class="code-header">
678
+ <span class="language-tag rust-tag">
679
+ <i class="fab fa-rust"></i> Полный код на Rust
680
+ </span>
681
+ <div class="code-actions">
682
+ <button class="btn-icon" onclick="copyCode('rust-complete')">
683
+ <i class="fas fa-copy"></i> Копировать
684
+ </button>
685
+ </div>
686
+ </div>
687
+ <div class="code-content">
688
+ <pre><code class="language-rust" id="rust-complete">use std::net::{UdpSocket, SocketAddr};
689
+ use std::sync::{Arc, mpsc};
690
+ use std::sync::atomic::{AtomicBool, Ordering};
691
+ use std::thread;
692
+ use std::time::{Duration, Instant};
693
+
694
+ const PORT: u16 = 11000;
695
+
696
+ fn main() {
697
+ println!("Запуск UDP сервера и клиента...");
698
+
699
+ let running = Arc::new(AtomicBool::new(true));
700
+
701
+ // Запускаем сервер
702
+ let server_running = start_udp_server(running.clone());
703
+
704
+ // Запускаем клиент в отдельном потоке
705
+ let client_running = running.clone();
706
+ let client_handle = thread::spawn(move || {
707
+ let rt = tokio::runtime::Runtime::new().unwrap();
708
+ rt.block_on(start_udp_client(client_running));
709
+ });
710
+
711
+ println!("Нажмите Enter для остановки...");
712
+ let mut input = String::new();
713
+ std::io::stdin().read_line(&mut input).unwrap();
714
+
715
+ // Останавливаем сервер и клиент
716
+ running.store(false, Ordering::Relaxed);
717
+
718
+ // Ждём завершения потоков
719
+ thread::sleep(Duration::from_secs(3));
720
+
721
+ println!("Программа завершена.");
722
+ }
723
+
724
+ pub fn start_udp_server(running: Arc&lt;AtomicBool&gt;) -> Arc&lt;AtomicBool&gt; {
725
+ let socket = UdpSocket::bind(("0.0.0.0", PORT))
726
+ .expect("Не удалось привязать сокет");
727
+
728
+ println!("UDP сервер запущен на порту {}", PORT);
729
+
730
+ let server_running = running.clone();
731
+
732
+ thread::spawn(move || {
733
+ let mut buf = [0; 1024];
734
+
735
+ while server_running.load(Ordering::Relaxed) {
736
+ match socket.recv_from(&mut buf) {
737
+ Ok((size, src)) => {
738
+ let data = &buf[..size];
739
+ let message = String::from_utf8_lossy(data);
740
+ println!("Получено от {}: {}", src, message);
741
+
742
+ if let Err(e) = socket.send_to(data, src) {
743
+ eprintln!("Ошибка отправки: {}", e);
744
+ }
745
+ }
746
+ Err(e) => {
747
+ eprintln!("Ошибка приёма: {}", e);
748
+ }
749
+ }
750
+ }
751
+ });
752
+
753
+ running
754
+ }
755
+
756
+ pub async fn start_udp_client(running: Arc&lt;AtomicBool&gt;) {
757
+ let socket = UdpSocket::bind("0.0.0.0:0")
758
+ .expect("Не удалось создать клиентский сокет");
759
+
760
+ let server_addr: SocketAddr = ("127.0.0.1", PORT).into();
761
+ let mut message_counter = 1;
762
+
763
+ while running.load(Ordering::Relaxed) {
764
+ let message = format!("Сообщение {}", message_counter);
765
+ let data = message.as_bytes();
766
+
767
+ let start_time = Instant::now();
768
+
769
+ if let Err(e) = socket.send_to(data, server_addr) {
770
+ eprintln!("Ошибка отправки: {}", e);
771
+ continue;
772
+ }
773
+
774
+ let mut buf = [0; 1024];
775
+ match socket.recv_from(&mut buf) {
776
+ Ok((size, _)) => {
777
+ let rtt = start_time.elapsed();
778
+ let response = String::from_utf8_lossy(&buf[..size]);
779
+
780
+ println!("Ответ от сервера: {} | RTT: {:.3} ms | PING: {:.3} ms",
781
+ response,
782
+ rtt.as_millis(),
783
+ rtt.as_millis() as f64 / 2.0);
784
+ }
785
+ Err(e) => {
786
+ eprintln!("Ошибка приёма: {}", e);
787
+ }
788
+ }
789
+
790
+ message_counter += 1;
791
+ thread::sleep(Duration::from_millis(1000));
792
+ }
793
+ }</code></pre>
794
+ </div>
795
+ <div class="dependencies">
796
+ <div class="dependencies-title">
797
+ <i class="fas fa-cube"></i> Зависимости для Cargo.toml
798
+ </div>
799
+ <div class="dependencies-list">
800
+ [dependencies]
801
+ tokio = { version = "1.0", features = ["full"] }
802
+ </div>
803
+ </div>
804
+ </div>
805
+ </div>
806
+ </section>
807
+
808
+ <section id="explanation" class="explanation-section fade-in">
809
+ <div class="section-header">
810
+ <h2 class="section-title">
811
+ <i class="fas fa-graduation-cap"></i>
812
+ Ключевые отличия и особенности
813
+ </h2>
814
+ </div>
815
+
816
+ <div class="explanation-grid">
817
+ <div class="explanation-card">
818
+ <div class="card-icon">
819
+ <i class="fas fa-memory"></i>
820
+ </div>
821
+ <h3 class="card-title">Управление памятью</h3>
822
+ <p class="card-text">
823
+ Rust обеспечивает безопасность памяти без сборщика мусора. Вместо C# GC, Rust использует владение и заимствование для предотвращения ошибок.
824
+ </p>
825
+ </div>
826
+
827
+ <div class="explanation-card">
828
+ <div class="card-icon">
829
+ <i class="fas fa-sync-alt"></i>
830
+ </div>
831
+ <h3 class="card-title">Асинхронность</h3>
832
+ <p class="card-text">
833
+ Вместо Task.Run из C#, Rust использует async/await с рантаймом tokio. Асинхронный код в Rust компилируется в state machine.
834
+ </p>
835
+ </div>
836
+
837
+ <div class="explanation-card">
838
+ <div class="card-icon">
839
+ <i class="fas fa-shield-alt"></i>
840
+ </div>
841
+ <h3 class="card-title">Обработка ошибок</h3>
842
+ <p class="card-text">
843
+ Rust использует Result&lt;T, E&gt; вместо исключений C#. Это заставляет обрабатывать все возможные ошибки компилятором.
844
+ </p>
845
+ </div>
846
+
847
+ <div class="explanation-card">
848
+ <div class="card-icon">
849
+ <i class="fas fa-tachometer-alt"></i>
850
+ </div>
851
+ <h3 class="card-title">Производительность</h3>
852
+ <p class="card-text">
853
+ Код Rust компилируется в машинный код без накладных расходов рантайма, обеспечивая производительность на уровне C/C++.
854
+ </p>
855
+ </div>
856
+ </div>
857
+
858
+ <h3 style="margin-top: 2rem; margin-bottom: 1rem; font-size: 1.25rem; color: var(--text-primary);">
859
+ <i class="fas fa-list-check" style="color: var(--primary); margin-right: 0.5rem;"></i>
860
+ Преимущества конвертации в Rust
861
+ </h3>
862
+
863
+ <div class="features-grid">
864
+ <div class="feature-item">
865
+ <i class="fas fa-check-circle"></i>
866
+ <span>Нулевая стоимость абстракций</span>
867
+ </div>
868
+ <div class="feature-item">
869
+ <i class="fas fa-check-circle"></i>
870
+ <span>Безопасные потоки без data races</span>
871
+ </div>
872
+ <div class="feature-item">
873
+ <i class="fas fa-check-circle"></i>
874
+ <span>Детерминированное управление ресурсами</span>
875
+ </div>
876
+ <div class="feature-item">
877
+ <i class="fas fa-check-circle"></i>
878
+ <span>WebAssembly поддержка</span>
879
+ </div>
880
+ <div class="feature-item">
881
+ <i class="fas fa-check-circle"></i>
882
+ <span>Отличная экосистема (Cargo)</span>
883
+ </div>
884
+ <div class="feature-item">
885
+ <i class="fas fa-check-circle"></i>
886
+ <span>Безопасность без потери производительности</span>
887
+ </div>
888
+ </div>
889
+ </section>
890
+ </main>
891
+
892
+ <div id="toast" class="toast">
893
+ <i class="fas fa-check-circle"></i>
894
+ <span id="toast-message">Скопировано в буфер обмена!</span>
895
+ </div>
896
+
897
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js"></script>
898
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-csharp.min.js"></script>
899
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-rust.min.js"></script>
900
+ <script>
901
+ function switchTab(tabName) {
902
+ // Hide all tabs
903
+ document.querySelectorAll('.tab-content').forEach(tab => {
904
+ tab.classList.remove('active');
905
+ });
906
+
907
+ // Remove active class from all tab buttons
908
+ document.querySelectorAll('.tab').forEach(btn => {
909
+ btn.classList.remove('active');
910
+ });
911
+
912
+ // Show selected tab
913
+ document.getElementById(tabName + '-tab').classList.add('active');
914
+
915
+ // Add active class to clicked button
916
+ event.target.classList.add('active');
917
+
918
+ // Re-highlight code
919
+ Prism.highlightAll();
920
+ }
921
+
922
+ function copyCode(codeId) {
923
+ const codeElement = document.getElementById(codeId);
924
+ const text = codeElement.textContent;
925
+
926
+ navigator.clipboard.writeText(text).then(() => {
927
+ showToast('Код скопирован в буфер обмена!');
928
+ }).catch(err => {
929
+ console.error('Ошибка копирования:', err);
930
+ showToast('Ошибка копирования кода', 'error');
931
+ });
932
+ }
933
+
934
+ function showToast(message, type = 'success') {
935
+ const toast = document.getElementById('toast');
936
+ const toastMessage = document.getElementById('toast-message');
937
+
938
+ toastMessage.textContent = message;
939
+
940
+ if (type === 'error') {
941
+ toast.style.background = 'var(--error)';
942
+ } else {
943
+ toast.style.background = 'var(--success)';
944
+ }
945
+
946
+ toast.classList.add('show');
947
+
948
+ setTimeout(() => {
949
+ toast.classList.remove('show');
950
+ }, 3000);
951
+ }
952
+
953
+ function downloadRustCode() {
954
+ const rustCode = document.getElementById('rust-complete').textContent;
955
+ const cargoToml = `[dependencies]\ntokio = { version = "1.0", features = ["full"] }`;
956
+
957
+ const content = `// main.rs\n${rustCode}\n\n// Cargo.toml\n${cargoToml}`;
958
+
959
+ const blob = new Blob([content], { type: 'text/plain' });
960
+ const url = window.URL.createObjectURL(blob);
961
+ const a = document.createElement('a');
962
+ a.href = url;
963
+ a.download = 'udp_server_client_rust.txt';
964
+ document.body.appendChild(a);
965
+ a.click();
966
+ document.body.removeChild(a);
967
+ window.URL.revokeObjectURL(url);
968
+
969
+ showToast('Rust код загружен!');
970
+ }
971
+
972
+ // Add smooth scrolling
973
+ document.querySelectorAll('a[href^="#"]').forEach(anchor => {
974
+ anchor.addEventListener('click', function (e) {
975
+ e.preventDefault();
976
+ const target = document.querySelector(this.getAttribute('href'));
977
+ if (target) {
978
+ target.scrollIntoView({
979
+ behavior: 'smooth',
980
+ block: 'start'
981
+ });
982
+ }
983
+ });
984
+ });
985
+
986
+ // Add fade-in animation on scroll
987
+ const observerOptions = {
988
+ threshold: 0.1,
989
+ rootMargin: '0px 0px -50px 0px'
990
+ };
991
+
992
+ const observer = new IntersectionObserver((entries) => {
993
+ entries.forEach(entry => {
994
+ if (entry.isIntersecting) {
995
+ entry.target.style.opacity = '1';
996
+ entry.target.style.transform = 'translateY(0)';
997
+ }
998
+ });
999
+ }, observerOptions);
1000
+
1001
+ document.querySelectorAll('.fade-in').forEach(el => {
1002
+ el.style.opacity = '0';
1003
+ el.style.transform = 'translateY(20px)';
1004
+ el.style.transition = 'opacity 0.5s ease-out, transform 0.5s ease-out';
1005
+ observer.observe(el);
1006
+ });
1007
+
1008
+ // Initialize syntax highlighting
1009
+ Prism.highlightAll();
1010
+ </script>
1011
+ </body>
1012
+ </html>