jondurbin commited on
Commit
a1f6cc0
1 Parent(s): 9d66f17

Update README.md

Browse files
Files changed (1) hide show
  1. README.md +184 -0
README.md CHANGED
@@ -349,6 +349,190 @@ Now, your FastAPI webserver has a ping endpoint that returns the current date in
349
 
350
  </details>
351
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
352
  #### Word games / trivia
353
 
354
  ```
 
349
 
350
  </details>
351
 
352
+ <details>
353
+ <summary>Write a multi-threaded TCP server in C that accepts a "GET [key]" input and "SET [key] [value]" input, and uses a binary tree to get and store the input values.</summary>
354
+
355
+ Here's a simple implementation of a multi-threaded TCP server in C that accepts "GET [key]" and "SET [key] [value]" inputs, and uses a binary tree to store the input values.
356
+
357
+ ```c
358
+ #include <stdio.h>
359
+ #include <stdlib.h>
360
+ #include <sys/socket.h>
361
+ #include <netinet/in.h>
362
+ #include <unistd.h>
363
+ #include <string.h>
364
+ #include <pthread.h>
365
+
366
+ #define MAX_KEY_LEN 256
367
+ #define MAX_VALUE_LEN 256
368
+
369
+ typedef struct Node {
370
+ char key[MAX_KEY_LEN];
371
+ char value[MAX_VALUE_LEN];
372
+ struct Node* left;
373
+ struct Node* right;
374
+ } TreeNode;
375
+
376
+ TreeNode* tree = NULL;
377
+
378
+ void insert(char* key, char* value) {
379
+ TreeNode* parent = (TreeNode*)malloc(sizeof(TreeNode));
380
+ if (!parent) {
381
+ perror("malloc failed");
382
+ exit(1);
383
+ }
384
+
385
+ strcpy(parent->key, key);
386
+ strcpy(parent->value, value);
387
+
388
+ parent->left = parent->right = NULL;
389
+
390
+ if (!tree) {
391
+ tree = parent;
392
+ } else {
393
+ insert(parent->key, parent->value);
394
+ }
395
+ }
396
+
397
+ char* search(char* key) {
398
+ TreeNode* current = tree;
399
+ while (current != NULL) {
400
+ if (strcmp(key, current->key) == 0) {
401
+ return current->value;
402
+ }
403
+ current = current->right;
404
+ }
405
+
406
+ return NULL;
407
+ }
408
+
409
+ void print_tree() {
410
+ TreeNode* current = tree;
411
+ while (current != NULL) {
412
+ printf("%s = %s\n", current->key, current->value);
413
+ current = current->right;
414
+ }
415
+ }
416
+
417
+ void* accept_client(void* args) {
418
+ int client_socket = *(int*)args;
419
+ char buffer[1024];
420
+
421
+ while (1) {
422
+ ssize_t bytes_received = recv(client_socket, buffer, sizeof(buffer), 0);
423
+ if (bytes_received <= 0) {
424
+ close(client_socket);
425
+ break;
426
+ }
427
+
428
+ char* input = buffer;
429
+ char* input_token;
430
+
431
+ while ((input_token = strtok(input, " \n")) != NULL) {
432
+ switch (input_token[0]) {
433
+ case 'G':
434
+ if (!search(input_token)) {
435
+ perror("Value not found");
436
+ exit(1);
437
+ }
438
+ printf("%s = %s\n", input_token, search(input_token));
439
+ break;
440
+
441
+ case 'S':
442
+ if (!strcmp(input_token, "SET")) {
443
+ char* key = strtok(NULL, " \n");
444
+ char* value = strtok(NULL, " \n");
445
+ if (!key || !value) {
446
+ perror("Invalid input");
447
+ exit(1);
448
+ }
449
+
450
+ insert(key, value);
451
+ printf("%s set %s to %s\n", input_token, key, value);
452
+ } else {
453
+ perror("Invalid command");
454
+ exit(1);
455
+ }
456
+ break;
457
+
458
+ default:
459
+ perror("Invalid input");
460
+ exit(1);
461
+ }
462
+
463
+ input = strtok(NULL, " \n");
464
+ }
465
+ }
466
+
467
+ return NULL;
468
+ }
469
+
470
+ int main() {
471
+ int server_socket = socket(AF_INET, SOCK_STREAM, 0);
472
+ if (server_socket < 0) {
473
+ perror("socket failed");
474
+ exit(1);
475
+ }
476
+
477
+ struct sockaddr_in server_addr;
478
+ memset(&server_addr, 0, sizeof(server_addr));
479
+ server_addr.sin_family = AF_INET;
480
+ server_addr.sin_port = htons(8080);
481
+ server_addr.sin_addr.s_addr = INADDR_ANY;
482
+
483
+ if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
484
+ perror("bind failed");
485
+ exit(1);
486
+ }
487
+
488
+ if (listen(server_socket, 5) < 0) {
489
+ perror("listen failed");
490
+ exit(1);
491
+ }
492
+
493
+ pthread_t accept_thread;
494
+ pthread_create(&accept_thread, NULL, accept_client, &server_socket);
495
+
496
+ char* client_input;
497
+ int client_socket = accept(server_socket, (struct sockaddr*)NULL, NULL);
498
+ if (client_socket < 0) {
499
+ perror("accept failed");
500
+ exit(1);
501
+ }
502
+
503
+ while (1) {
504
+ sleep(1);
505
+
506
+ char buffer[1024];
507
+ ssize_t bytes_received = recv(client_socket, buffer, sizeof(buffer), 0);
508
+ if (bytes_received <= 0) {
509
+ close(client_socket);
510
+ break;
511
+ }
512
+
513
+ client_input = buffer;
514
+ parse_input(client_input);
515
+ }
516
+
517
+ close(client_socket);
518
+ pthread_join(accept_thread, NULL);
519
+
520
+ return 0;
521
+ }
522
+ ```
523
+
524
+ To compile and run this code, save it to a file named `multi_threaded_tcp_server.c`, then use the following commands:
525
+
526
+ ```sh
527
+ gcc -o multi_threaded_tcp_server multi_threaded_tcp_server.c
528
+ ./multi_threaded_tcp_server
529
+ ```
530
+
531
+ This implementation creates a simple binary tree to store the input values. The accept() function creates a new thread for each client connection, which handles the incoming data and forwards it to the main thread. The main thread parses the input string and handles SET and GET commands.
532
+
533
+ Note that this code is not production-ready and should be improved with proper error handling, security checks, and a more efficient data structure for the binary tree.
534
+
535
+ </details>
536
  #### Word games / trivia
537
 
538
  ```