How to write a multithreaded server in C (threads, sockets)

Поділитися
Вставка
  • Опубліковано 18 вер 2024

КОМЕНТАРІ • 83

  • @Runeite51
    @Runeite51 Рік тому +24

    most unexpected programming video intro

  • @terigopula
    @terigopula 3 роки тому +22

    Explaining concepts with code is pure gold..! As Linus Torvalds says, "Talk is cheap show me the code".

  • @ajidaniel8818
    @ajidaniel8818 4 роки тому +41

    If you are a teacher , i am sure you will produce a bunch of very good programmers.
    Simple, Clear and Crisp , keep up the good work

    • @JacobSorber
      @JacobSorber  4 роки тому +25

      Thanks. I am a teacher, and producing very good programmers is one of my goals.

  • @eduardonolla9470
    @eduardonolla9470 2 роки тому +3

    I have been trying to get my threads running for 3 whole days. After using your method of passing the sockets as pointers my problem was solved. Thank you so much

  • @marshalstewart7776
    @marshalstewart7776 4 роки тому +13

    Been really starting to get into computer science and these videos are always interesting and helpful!

    • @JacobSorber
      @JacobSorber  4 роки тому +3

      Thanks. Glad they're helping.

  • @dhruvandangar8005
    @dhruvandangar8005 2 роки тому +1

    The intro was just lit.
    Rainy season touch my heart.

  • @mahamanebana4410
    @mahamanebana4410 3 роки тому +2

    I'm from Africa. Really appreciate your work

    • @JacobSorber
      @JacobSorber  3 роки тому +1

      Glad I could help. Where in Africa?

  • @copierofvideos2
    @copierofvideos2 3 роки тому +7

    Man this was great thanks! I always felt like c was a shitty language, but I can see that I just have to get more experience with it

    • @Kotesu
      @Kotesu 3 роки тому +3

      It's definitely not for every application, but it is often indispensable for many subdisciplines like kernels, embedded systems, scientific computing, games and other high-performance systems. It's a tricky language if you're coming from a pure compsci background: for most people C is as close to the silicon as they will ever get., and going any closer usually requires assembly. Coding in C requires a lot of patience and discipline but the payoff in performance, memory footprint and overall control of your processor can be well worth the effort.

    • @cusematt23
      @cusematt23 9 місяців тому +1

      @@Kotesu very well said. It's actually too bad your comment was buried in a reply because I think a lot of new programmer's would have an "ah ha" moment reading it.

  • @sushmitagoswami2033
    @sushmitagoswami2033 Рік тому +2

    Much respect to you sir! Thanks for sharing the knowledge

  • @anwarpenn
    @anwarpenn Рік тому +1

    Thank you so much for sharing! very insightful!

  • @elliotalderson9889
    @elliotalderson9889 Рік тому +1

    super cool tutorial. Thank you so much!

  • @whodaFru4551
    @whodaFru4551 5 років тому +4

    thats the kind of videos i like. very interesting!

  • @foxred2380
    @foxred2380 3 роки тому +1

    Excellent video, I enjoy explanation.

  • @lordadamson
    @lordadamson 5 років тому +3

    Awesome stuff Jacob :D

  • @Huhnmonster
    @Huhnmonster 5 років тому +5

    Hello Jacob, thank you very much for your content. Would it be possible that you go over evented web servers some day? I would like to get your take on event loops and maybe even a small introduction to select or epoll/kqueue.

    • @JacobSorber
      @JacobSorber  5 років тому +7

      Yeah, I think so. I'll put event-driven processing and servers (and epoll/kqueue) on my list for future video.

  • @cellularmitosis2
    @cellularmitosis2 4 роки тому +1

    Thank you so much for making these videos!

  • @Diddy10443
    @Diddy10443 4 роки тому +9

    2:29 "It is a truth universally acknowledged, that a single man in possession of a good fortune, must be in want of a wife..." hahaha

  • @gamezone4470
    @gamezone4470 4 роки тому +3

    you are a fantastic, thank you very much ..... I have a question, I don't know if you can help me but I want to know how to create multiple processes that connect to the apache web server, establish a connection and keep it waiting, just wait for the server timeout , and when the connection is lost, the process should restart it.
    In the end what I want is to see the simultaneous connections the web server can support, using a C language and fork () processes, the parent process will count how many processes achieve controls and many don't.

    • @JacobSorber
      @JacobSorber  4 роки тому +1

      You're welcome. It sounds like an interesting experiment. I'm not sure from the comment what sort of help you're looking for, but I'd love to hear how things go.

  • @gavdev12
    @gavdev12 2 роки тому +1

    Very well done video

  • @nafisehvalizadeh1011
    @nafisehvalizadeh1011 2 роки тому +2

    Hi Jacob, thanks for the tutorial. there is one thing I don't get that is every object (HTTP, image files, ..) request handled by a specific thread?

  • @vishwaspaikra795
    @vishwaspaikra795 Рік тому +1

    is it a good idea to give each client a thread? is it dangerous? Is it a good idea to handle client request with accept or epoll and assign a thread for a specific task?
    which is better?

  • @juanmamani2110
    @juanmamani2110 Рік тому +1

    Exactly what I was looking for. Thanks for sharing!
    Which c compiler did you use?

  • @pikimk6167
    @pikimk6167 Рік тому +1

    Hi Jacob, i love your videos and could you do a libuv tutorial? I think it will be a fun topic to watch.

  • @adityavikram5176
    @adityavikram5176 3 роки тому +1

    Awesome video!!

  • @mohammedzaid6634
    @mohammedzaid6634 3 роки тому +2

    hey jacob i didn't get the error that you did in 5:35 even though my backlog=1 on listen function

  • @axramar1992
    @axramar1992 4 місяці тому +1

    Hi please do some tutorials on EC200U opencpu .

  • @karthikp3329
    @karthikp3329 2 роки тому +1

    Please correct me if I am wrong:
    If there is pointer to a dynamically allocated memory in calling function and it is passed as an argument to called function (as you did in the case of handleConnection() function), will it not cause a dangling pointer in calling function if the memory is freed in called function?
    I think it's better to free the memory in calling function (or parent thread) and to be safer, after child thread joining. I guess the pointer in new thread function will have no effect once the function returns and frame is removed from function call stack.

  • @Teog1992
    @Teog1992 4 роки тому +2

    great videos ! Just wanted to ask , the first implementation of the threat , is essentially a producer/consumer model without a queue ?

    • @JacobSorber
      @JacobSorber  4 роки тому +3

      ...where the producer creates the consumers, yes.

  • @akshithbellare7568
    @akshithbellare7568 4 роки тому +3

    Hey I needed help with listening from two ports at the same time.What should I do for it?

    • @JacobSorber
      @JacobSorber  4 роки тому +3

      You could use two listening threads, one listening on each port. You could use select (maybe a good topic for a future video). You could also make the sockets nonblocking.

    • @akshithbellare7568
      @akshithbellare7568 4 роки тому +2

      @@JacobSorber We used select , and our project works :)

  • @techtechlearn3438
    @techtechlearn3438 2 роки тому +1

    how many cores/threads does your "server" (which I presume it's the actual host pc you are using) have, just so that I can image how many threads can actually run in parallel at once? Thank you!!!

  • @gaddeshamena6781
    @gaddeshamena6781 3 роки тому +1

    Well said sir😊😊

  • @hirenpatel6118
    @hirenpatel6118 3 роки тому +2

    Hi Jacob, confused as to why the value of client_socket is being copied to the heap? When the while loop starts again, shouldn't the new accept call return a different file descriptor than the last iteration? If we pass the file descriptor by value vs by reference we should be fine right?

    • @tejastatineni7527
      @tejastatineni7527 Рік тому +1

      Exactly my doubt. It doesn't make sense to create a pointer just for storing the client_socket and deleting it in the handle_connection method.

  • @meluobote7664
    @meluobote7664 4 роки тому +2

    very beautful code, what your IDE is? Is computer system Linux?

  • @lania4334
    @lania4334 3 роки тому +2

    Can you help me
    How make this code when we have multiple clients just one client connect that server and the other clients wait for response's server until that client is completed

    • @JacobSorber
      @JacobSorber  3 роки тому +2

      This server should be able to handle multiple clients. It handles each connection in a separate thread, so as long as your connection handling can be done concurrently, then connections shouldn't have to wait.

    • @lania4334
      @lania4334 3 роки тому +1

      @@JacobSorber I know but it is my homework

    • @ayoubazacri7234
      @ayoubazacri7234 2 роки тому +1

      @@lania4334 i have the same homework, could please send it to me , I'll appreciate that.

  • @andreykrasnov7851
    @andreykrasnov7851 4 роки тому +1

    Thank you for very good video, Jacob! Is it possible to find somewhere source code you use here?

  • @leokiller123able
    @leokiller123able 3 роки тому +1

    Would it make it faster if we use fork() instead of threads?

    • @JacobSorber
      @JacobSorber  3 роки тому +5

      Probably not. Creating a new process should be more work than creating a new thread.

  • @LinucNerd
    @LinucNerd 5 років тому +7

    Please do a tutorial about Unicode, pls, I need this :c

    • @JacobSorber
      @JacobSorber  5 років тому +4

      It's definitely coming. I've been thinking about this topic, but life's busy, and it might take a little while to show up in video form.

  • @SuperCape
    @SuperCape 5 років тому +4

    What's gonna happen if you pull a SlowLoris DoS attack on this server?

    • @YashasviGoel
      @YashasviGoel 5 років тому +2

      Would be interesting to see some modifications to this server in order to handle them.

    • @JacobSorber
      @JacobSorber  5 років тому +2

      Try it out and see. :)

  • @wildchild01
    @wildchild01 4 роки тому +1

    Hi Jacob, can you tell me more about the function "check" that you created? I want to use it in my code too. Thanks!

    • @mohammedzaid6634
      @mohammedzaid6634 3 роки тому +1

      int check(int exp, const char *msg)
      {
      if (exp == SOCKETERROR)
      {
      perror(msg);
      exit(EXIT_FAILURE);
      }
      return exp;
      }

  • @gurjaschawla1019
    @gurjaschawla1019 Рік тому +1

    Hi, I can't find the source code on Patreon . can someone send me . Will be very appreciated , Thanks

  • @Елена-й2б7щ
    @Елена-й2б7щ Рік тому +1

    How to terminate threads explicit?

  • @Marblewho
    @Marblewho 4 роки тому +1

    What if the handle connection function takes more than one argument?

    • @JacobSorber
      @JacobSorber  4 роки тому +2

      A thread function only takes one argument (void*). One way to do it would be to create a struct with all the things you want to pass in, and then pass a pointer to that struct.

    • @Marblewho
      @Marblewho 4 роки тому +1

      Jacob Sorber Cool, thank you!

  • @enioladare4967
    @enioladare4967 2 роки тому +1

    You were a professor at botho right?

  • @Nothing-dq5rx
    @Nothing-dq5rx Рік тому +1

    Priority Multithreading tcp please

    • @JacobSorber
      @JacobSorber  Рік тому +1

      Meaning that you would like me to prioritize multithreading TCP, or that you want some sort of example where you prioritize different threads managing TCP connections?

    • @Nothing-dq5rx
      @Nothing-dq5rx Рік тому +1

      @@JacobSorber I want some sort of example that prioritise for different threads with timing signal also managing threads for tcp transmission

    • @Nothing-dq5rx
      @Nothing-dq5rx Рік тому +1

      Sorry for late reply

    • @Nothing-dq5rx
      @Nothing-dq5rx Рік тому

      Multi Process scheduling with time slice between different process and diffrent priorities to different process

  • @gaddeshamena6781
    @gaddeshamena6781 3 роки тому +1

    Sir I have aa doubt please can u help me can I send u in mail

    • @JacobSorber
      @JacobSorber  3 роки тому +2

      Hi Gadde. I prefer to keep questions here on UA-cam both so they can help more people, but also because I don't always have time to answer them all. If the questions are posted publically, often someone can answer it before I get to it. Of course, I do provide more one-on-one interaction through Patreon.

    • @gaddeshamena6781
      @gaddeshamena6781 3 роки тому +1

      @@JacobSorber sir actually I want to show u in document sir

    • @gaddeshamena6781
      @gaddeshamena6781 3 роки тому +1

      @@JacobSorber Develop a basic multithreaded webserver (where multiple threads process multiple client requests simultaneously) with support for different scheduling policies for the client requests....this is the question sir but we have to write in given template

    • @gaddeshamena6781
      @gaddeshamena6781 3 роки тому

      #include "io_helper.h"
      #include "request.h"
      #define MAXBUF (8192)
      //
      // TODO: add code to create and manage the buffer
      //
      //
      // Sends out HTTP response in case of errors
      //
      void request_error(int fd, char *cause, char *errnum, char *shortmsg, char *longmsg) {
      char buf[MAXBUF], body[MAXBUF];
      // Create the body of error message first (have to know its length for header)
      sprintf(body, ""
      "
      "
      "
      "
      " OSTEP WebServer Error
      "
      "
      "
      "
      "
      " %s: %s
      "
      " %s: %s
      "
      "
      "
      "
      ", errnum, shortmsg, longmsg, cause);
      // Write out the header information for this response
      sprintf(buf, "HTTP/1.0 %s %s
      ", errnum, shortmsg);
      write_or_die(fd, buf, strlen(buf));
      sprintf(buf, "Content-Type: text/html
      ");
      write_or_die(fd, buf, strlen(buf));
      sprintf(buf, "Content-Length: %lu

      ", strlen(body));
      write_or_die(fd, buf, strlen(buf));
      // Write out the body last
      write_or_die(fd, body, strlen(body));
      // close the socket connection
      close_or_die(fd);
      }
      //
      // Reads and discards everything up to an empty text line
      //
      void request_read_headers(int fd) {
      char buf[MAXBUF];
      readline_or_die(fd, buf, MAXBUF);
      while (strcmp(buf, "
      ")) {
      readline_or_die(fd, buf, MAXBUF);
      }
      return;
      }
      //
      // Return 1 if static, 0 if dynamic content (executable file)
      // Calculates filename (and cgiargs, for dynamic) from uri
      //
      int request_parse_uri(char *uri, char *filename, char *cgiargs) {
      char *ptr;
      if (!strstr(uri, "cgi")) {
      // static
      strcpy(cgiargs, "");
      sprintf(filename, ".%s", uri);
      if (uri[strlen(uri)-1] == '/') {
      strcat(filename, "index.html");
      }
      return 1;
      } else {
      // dynamic
      ptr = index(uri, '?');
      if (ptr) {
      strcpy(cgiargs, ptr+1);
      *ptr = '\0';
      } else {
      strcpy(cgiargs, "");
      }
      sprintf(filename, ".%s", uri);
      return 0;
      }
      }
      //
      // Fills in the filetype given the filename
      //
      void request_get_filetype(char *filename, char *filetype) {
      if (strstr(filename, ".html"))
      strcpy(filetype, "text/html");
      else if (strstr(filename, ".gif"))
      strcpy(filetype, "image/gif");
      else if (strstr(filename, ".jpg"))
      strcpy(filetype, "image/jpeg");
      else
      strcpy(filetype, "text/plain");
      }
      //
      // Handles requests for static content
      //
      void request_serve_static(int fd, char *filename, int filesize) {
      int srcfd;
      char *srcp, filetype[MAXBUF], buf[MAXBUF];
      request_get_filetype(filename, filetype);
      srcfd = open_or_die(filename, O_RDONLY, 0);
      // Rather than call read() to read the file into memory,
      // which would require that we allocate a buffer, we memory-map the file
      srcp = mmap_or_die(0, filesize, PROT_READ, MAP_PRIVATE, srcfd, 0);
      close_or_die(srcfd);
      // put together response
      sprintf(buf, ""
      "HTTP/1.0 200 OK
      "
      "Server: OSTEP WebServer
      "
      "Content-Length: %d
      "
      "Content-Type: %s

      ",
      filesize, filetype);
      write_or_die(fd, buf, strlen(buf));
      // Writes out to the client socket the memory-mapped file
      write_or_die(fd, srcp, filesize);
      munmap_or_die(srcp, filesize);
      }
      //
      // Fetches the requests from the buffer and handles them (thread locic)
      //
      void* thread_request_serve_static(void* arg)
      {
      // TODO: write code to actualy respond to HTTP requests
      }
      //
      // Initial handling of the request
      //
      void request_handle(int fd) {
      int is_static;
      struct stat sbuf;
      char buf[MAXBUF], method[MAXBUF], uri[MAXBUF], version[MAXBUF];
      char filename[MAXBUF], cgiargs[MAXBUF];
      // get the request type, file path and HTTP version
      readline_or_die(fd, buf, MAXBUF);
      sscanf(buf, "%s %s %s", method, uri, version);
      printf("method:%s uri:%s version:%s
      ", method, uri, version);
      // verify if the request type is GET is not
      if (strcasecmp(method, "GET")) {
      request_error(fd, method, "501", "Not Implemented", "server does not implement this method");
      return;
      }
      request_read_headers(fd);
      // check requested content type (static/dynamic)
      is_static = request_parse_uri(uri, filename, cgiargs);
      // get some data regarding the requested file, also check if requested file is present on server
      if (stat(filename, &sbuf) < 0) {
      request_error(fd, filename, "404", "Not found", "server could not find this file");
      return;
      }
      // verify if requested content is static
      if (is_static) {
      if (!(S_ISREG(sbuf.st_mode)) || !(S_IRUSR & sbuf.st_mode)) {
      request_error(fd, filename, "403", "Forbidden", "server could not read this file");
      return;
      }
      // TODO: write code to add HTTP requests in the buffer based on the scheduling policy
      } else {..
      We have to write in this format sir

    • @gaddeshamena6781
      @gaddeshamena6781 3 роки тому +1

      @@JacobSorber please sir would u solve it it is very urgent sir

  • @markmanning2921
    @markmanning2921 7 місяців тому +3

    how common is it for a server to rip the rug out from under every connection just because one request from the client has been acted on. I dont think this is a very good example, it is next to useless for an actual real life purpose

  • @ragnarlothbrok367
    @ragnarlothbrok367 2 роки тому +3

    too hard to understand

  • @MaiHappyBanda
    @MaiHappyBanda 2 роки тому +1

    i thought its a vlog

  • @foodsweets2728
    @foodsweets2728 3 роки тому +1

    You are too good but too fast, cant really follow.

  • @tw7522
    @tw7522 Рік тому +1

    This code is horrible. Seriously, you should take the video down.

    • @RoofusRoof19
      @RoofusRoof19 3 місяці тому +1

      ok send me a better example