c recv() read until newline occurs

后端 未结 2 798
太阳男子
太阳男子 2021-01-11 18:03

I\'m working on writing a IRC bot in C, and have ran into a snag.

In my main function, I create my socket and connect, all that happy stuff. Then I have a (almost) i

2条回答
  •  一生所求
    2021-01-11 18:57

    The usual way to deal with this is to recv into a persistent buffer in your application, then pull a single line out and process it. Later you can process the remaining lines in the buffer before calling recv again. Keep in mind that the last line in the buffer may only be partially received; you have to deal with this case by re-entering recv to finish the line.

    Here's an example (totally untested! also looks for a \n, not \r\n):

    #define BUFFER_SIZE 1024
    char inbuf[BUFFER_SIZE];
    size_t inbuf_used = 0;
    
    /* Final \n is replaced with \0 before calling process_line */
    void process_line(char *lineptr);
    void input_pump(int fd) {
      size_t inbuf_remain = sizeof(inbuf) - inbuf_used;
      if (inbuf_remain == 0) {
        fprintf(stderr, "Line exceeded buffer length!\n");
        abort();
      }
    
      ssize_t rv = recv(fd, (void*)&inbuf[inbuf_used], inbuf_remain, MSG_DONTWAIT);
      if (rv == 0) {
        fprintf(stderr, "Connection closed.\n");
        abort();
      }
      if (rv < 0 && errno == EAGAIN) {
        /* no data for now, call back when the socket is readable */
        return;
      }
      if (rv < 0) {
        perror("Connection error");
        abort();
      }
      inbuf_used += rv;
    
      /* Scan for newlines in the line buffer; we're careful here to deal with embedded \0s
       * an evil server may send, as well as only processing lines that are complete.
       */
      char *line_start = inbuf;
      char *line_end;
      while ( (line_end = (char*)memchr((void*)line_start, '\n', inbuf_used - (line_start - inbuf))))
      {
        *line_end = 0;
        process_line(line_start);
        line_start = line_end + 1;
      }
      /* Shift buffer down so the unprocessed data is at the start */
      inbuf_used -= (line_start - inbuf);
      memmove(innbuf, line_start, inbuf_used);
    }
    

提交回复
热议问题