Algorithm 处理来自套接字的分段输入的通用方法

Algorithm 处理来自套接字的分段输入的通用方法,algorithm,sockets,language-agnostic,stream,Algorithm,Sockets,Language Agnostic,Stream,这个问题有点笼统,但我发现自己在过去几年的各种情况下都遇到了这个问题,所以我想一定有一个标准的解决方案 我想知道是否有标准算法用于处理这样的情况,即使用某种专有协议从某种套接字/流读取数据,但消息不能保证以整块的形式到达 我在各种不同的协议和各种套接字/流(如串行端口、TCP套接字、UNIX套接字)中遇到了这个问题,目前在C中有一个蓝牙流 为了说明这一点,让我试着给出一个简单的例子: //A simple protocol where a message starts with a #, //e

这个问题有点笼统,但我发现自己在过去几年的各种情况下都遇到了这个问题,所以我想一定有一个标准的解决方案

我想知道是否有标准算法用于处理这样的情况,即使用某种专有协议从某种套接字/流读取数据,但消息不能保证以整块的形式到达

我在各种不同的协议和各种套接字/流(如串行端口、TCP套接字、UNIX套接字)中遇到了这个问题,目前在
C
中有一个蓝牙流

为了说明这一点,让我试着给出一个简单的例子:

//A simple protocol where a message starts with a #,
//ends with a *, and has the header separated with a ;
#somemessage;somedatahere* 

//A read operation on a socket may yield:
#somemessage;some  //can be truncated
#somemessage;somedatahere*#someme //can be a full message with additional bytes appended
ssage;somedatahere*#somemessage;somedatahere* //prepended bytes
在过去,我将任何读入的内容复制到“工作缓冲区”,并跟踪我在该缓冲区中的索引。然后,当我找到一条完整的消息时,我会将其从工作缓冲区中删除,但我以前遇到过这样的情况,即在缓冲区的前面堆积了一堆垃圾


其他人采取什么方法?我相对缺乏经验,我的背景是数字编码,这在以前从来都不是一个问题。

这个问题确实有点太笼统了:答案取决于协议如何定义消息边界。AFAIU,您提到的垃圾实际上是前一条消息的尾部部分;不知怎的,它的头部被遗漏了。在这种情况下,您只能忽略所有内容,直到识别出下一条消息的开头。如果协议没有明确地在流中分隔消息,通常您必须关闭连接并重新开始。

如果您想要处理符合特定语法的外部流,您应该实现一个接受该语法的解析器,并以某种方式报告语法错误。无论您是从文件读取还是从TCP/IP读取,都是如此

您可以编写解析器,以便它一次处理(接受)一个字节或字符。解析器将需要一些状态变量。其中一些是缓冲区

对于文本流,大多数语法可以表示为符号的排列,使用一组规则表示单个符号的标识。这自然会产生一个分为两部分的解析器,其中一部分(lexer)用于识别符号,并将其传递给解析器的其余部分

我喜欢使用准有限状态机解析器。在Java中,该解析器的基础代码如下:

 public abstract class Parser
 {

    protected abstract class State {

       public abstract State parse(char c);

       public abstract void parseEOF();

    }

    private State currentState;

    protected abstract State getStartState();

    public final void parse(char c) {
       currentState = currentState.parse(c);
    }

    public final void parseEOF() {
       currentState.parseEOF();
       currentState = null;
    }

    public final void parse(InputStream input) {
       currentState = getStartState();
       char c;
       while((c = input.read()) != -1) {
          parse(c);
       }
       parseEOF();
    }
 }