c recv() 读取直到出现换行符

标签 c sockets recv

我正在用 C 编写一个 IRC 机器人,但遇到了一个障碍。

在我的主要功能中,我创建了我的套接字并连接,所有这些令人愉快的事情。然后我有一个(几乎)无限循环来读取从服务器发回的内容。然后我将读取的内容传递给辅助函数 processLine(char *line) - 问题是,以下代码一直读取到我的缓冲区已满 - 我希望它只读取文本直到换行符(\n) 或回车 (\r) 发生(因此结束该行)

   while (buffer[0] && buffer[1]) {
        for (i=0;i<BUFSIZE;i++) buffer[i]='\0';
        if (recv(sock, buffer, BUFSIZE, 0) == SOCKET_ERROR)
            processError();

        processLine(buffer);
    }

最终发生的事情是很多线路都卡在了一起,发生这种情况时我无法正确处理这些线路。

如果您不熟悉 IRC 协议(protocol),一个简短的总结是当一条消息被发送时,它通常看起来像这样: :YourNickName!YourIdent@YourHostName PRIVMSG #someChannel :下面是发送的消息... 和登录通知,例如,是这样的: - 即 372 表示以下文本是今日消息的一部分。

当它们全部挤在一起时,我看不懂哪一行的数字是多少,因为我找不到一行的开始或结束位置!

非常感谢您的帮助!

P.S.:这是在 linux 上编译/运行的,但我最终想将它移植到 windows,所以我尽可能多地制作它的多平台。

P.S.S.:这是我的 processLine() 代码:

void processLine(const char *line) {
    char *buffer, *words[MAX_WORDS], *aPtr;
    char response[100];
    int count = 0, i;
    buffer = strdup(line);

    printf("BLA %s", line);

    while((aPtr = strsep(&buffer, " ")) && count < MAX_WORDS)
        words[count++] = aPtr;
        printf("DEBUG %s\n", words[1]);
    if (strcmp(words[0], "PING") == 0) {
        strcpy(response, "PONG ");
        strcat(response, words[1]);
        sendLine(NULL, response); /* This is a custom function, basically it's a send ALL function */
    } else if (strcmp(words[1], "376") == 0) { /* We got logged in, send login responses (i.e. channel joins) */
        sendLine(NULL, "JOIN #cbot");
    }
}

最佳答案

处理此问题的通常方法是将recv 放入应用程序的持久缓冲区中,然后拉出一行并处理它。稍后您可以在再次调用 recv 之前处理缓冲区中的剩余行。请记住,缓冲区中的最后一行可能只被部分接收;您必须通过重新输入 recv 来完成该行来处理这种情况。

这是一个示例(完全未经测试!还查找 \n,而不是 \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);
}

关于c recv() 读取直到出现换行符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6090594/

相关文章:

c++ - C++中的多线程,从套接字接收消息

线程池可以运行在单线程函数上吗?

c - Gtk : get usable area of each monitor (excluding panels)

C++ 非阻塞套接字 - 等待所有接收数据

java - 从 InputStream JAVA 读取不同的输入

c++ - recv() 没有收到预期的字节数

c - Linux 在崩溃时自动重启应用程序 - 守护进程

c - 如何在 C 中取消分割 strtok 字符串?

linux - 动态更改套接字选项

linux - Socket Send(2) - 如何从服务器向客户端发送错误信息