代码之家  ›  专栏  ›  技术社区  ›  LukeN

从字符串中可靠地拆分行

  •  1
  • LukeN  · 技术社区  · 15 年前

    我在C语言中编写了一个小型服务器守护进程,处理连接、断开连接和接收等基本部分已经存在,但接收方面的问题仍然存在。

    我使用“recv”将256个字节一次读取到一个char数组中,因为它可以包含多行数据作为一个大块,所以我需要能够将每行分开来处理它。 仅此一点并不是问题所在,但由于一条线可能因为不再适合缓冲区而被切断,所以我还需要能够看到一条线是否被切断。也不错,只需检查最后一个字符 \r \n 但是什么 如果 线路被切断了?我的代码不允许简单地“继续读取更多数据”,因为我正在使用 select() 处理多个请求。

    基本上,这是我的情况:

    //This is the chunk of code ran after select(), when a socket
    //has readable data
    char buf[256] = { 0 };
    int nbytes;
    
    if ((nbytes = recv(i, buf, sizeof(buf) - 1, 0)) <= 0)
    {   
       if (nbytes == 0)
       {   
          struct remote_address addr;
    
          get_peername(i, &addr);
          do_log("[Socket #%d] %s:%d disconnected", i, addr.ip, addr.port);
       }   
       else
          do_log("recv(): %s", strerror(errno));
    
       close(i);
       FD_CLR(i, &clients);
    }   
    else
    {   
       buf[sizeof(buf) - 1] = 0;
       struct remote_address addr;
    
       get_peername(i, &addr);
       do_log("[Socket #%d] %s:%d (%d bytes): %s", i, addr.ip, addr.port, nbytes, buf);
    
       // split "buf" here, and process each line
       // but how to be able to get the rest of a possibly cut off line
       // in case it did not fit into the 256 byte buffer?
    }
    

    我在想有一个更大范围的临时缓冲变量(可能 malloc() 'd)如果当前缓冲区太长,无法立即容纳,则将其保存在中,但如果有更好的解决方案,我总是对引入不必要的高范围变量感到不安:/

    我很欣赏指点( 除了XKCD的那些:) )!

    2 回复  |  直到 15 年前
        1
  •  3
  •   Tronic    15 年前

    我想您需要添加另一个每流缓冲区,它保存不完整的行,直到接收到后面的换行。

        2
  •  0
  •   Jack    15 年前

    我会使用某种动态扩展的缓冲区,比如 GString 积累数据。

    另一个可能有帮助的方法是使用 fcntl() . 然后你可以 recv() 在一个循环中直到你得到-1。检查 errno ,也可以是 EAGAIN EWOULDBLOCK (而那些不需要具有相同的值:检查两者)。

    最后一句话:我发现使用libev(google i t;我不能发布多个链接)比使用libev更有趣。 select() .