检查通过程序的C管道 - 边界情况

时间:2009-05-25 18:38:24

标签: c sockets buffering

我从套接字A接收并将其写入套接字B(如代理服务器可能)。我想检查并可能修改传递的数据。我的问题是如何处理边界情况,即我正在搜索的正则表达式在两个连续的套接字A读取和套接字B写入迭代之间匹配。

char buffer[4096]
int socket_A, socket_B

/* Setting up the connection goes here */

for(;;) {

    recv(socket_A, buffer, 4096, 0);

    /* Inspect, and possibly modify buffer */

    send(socket_B, buffer, 4096, 0);

    /* Oops, the matches I was looking for were at the end of buffer,
     * and will be at the beginning of buffer next iteration :( */

}

6 个答案:

答案 0 :(得分:1)

我的建议:有两个缓冲区,并在它们之间轮换:

  1. Recv buffer 1
  2. Recv buffer 2
  3. 过程。
  4. 发送缓冲区1
  5. Recv buffer 1
  6. 处理,但在缓冲区1之前使用缓冲区2。
  7. 发送缓冲区2
  8. 转到2。
  9. 或类似的东西?

答案 1 :(得分:1)

假设您知道可能的正则表达式的最大长度M匹配(或者可以使用任意值 - 或者仅使用整个缓冲区),您可以通过不传递完整缓冲区但保留M-1字节来处理它背部。在下一次迭代中,将新接收的数据放在M-1字节的末尾并应用正则表达式。

如果您知道所传输数据的格式(例如http),您应该能够解析内容以了解何时到达通信结束并且应该发送您可能已缓存的尾随字节。如果您不知道格式,那么您需要在recv中实现超时,这样您就不会长时间保持通信结束。太长的事情是你必须自己决定的事情,

答案 2 :(得分:1)

从这个意义上说,你所谈论的(并且所有感官,比方说,TCP)套接字都是流。根据您的问题,您在数据中有一些结构。所以你必须做类似以下的事情:

  1. 缓冲(保持)传入数据,直到达到边界。边界可能是行尾,记录结束或您知道正则表达式匹配的任何其他方式。
  2. 当“记录”准备就绪时,处理它并将结果放在输出缓冲区中。
  3. 写入输出缓冲区中累积的任何内容。
  4. 处理大多数情况。如果你有一个罕见的情况,那里真的没有“记录”,那么你必须构建某种状态机(DFA)。我的意思是你必须能够积累数据,直到a)它不能匹配你的正则表达式,或b)它是一个完整的匹配。

    修改 如果您匹配固定字符串而不是真正的正则表达式,那么您应该能够使用Boyer-Moore算法,该算法实际上可以在子线性时间内运行(通过跳过字符)。如果你做得对,当你移动输入时,可以随时将先前看到的数据抛出到输出缓冲区,从而显着减少延迟并提高吞吐量。

答案 3 :(得分:1)

您需要了解和/或说出正则表达式。

根据正则表达式的不同,您可能需要比现在缓冲更多的缓冲区。

最糟糕的情况可能是正则表达式,它说“找到所有内容,从开头直到第一次出现'狗'这个词,并用其他东西代替”:如果你有一个常规的话这样的表达式,那么你需要缓冲(不转发)从开始到第一次出现“狗”这个词的所有内容:这可能永远不会发生,也就是说可能是无限量的缓冲。

答案 4 :(得分:0)

基本上,代码的问题在于recv / send循环在比修改更低的网络层上运行。您如何解决此问题取决于您正在进行哪些修改,但它可能涉及缓冲数据,直到可以进行所有本地修改。

编辑:我不知道任何可以过滤这样的流的正则表达式库。这将有多难取决于你的正则表达式和它正在过滤的协议。

答案 5 :(得分:0)

一种替代方法是使用poll(2) - 类似于非阻塞套接字的策略。在read事件中从套接字中获取缓冲区,将其推送到传入队列,调用将缓冲区组装成流的lexer / parser / matcher,然后将块推送到输出队列。在写入事件时,从输出队列中取出一个块(如果有),并将其写入套接字。这听起来有点复杂,但是一旦你习惯了倒置控制模型,它就不是真的了。