有没有办法在套接字接收中引入分隔符?

Is there a way to introduce a separator in socket reception?

我正在使用 C# 套接字通信,我收到不同的消息,由特殊字符 (ASCII code 3) 分隔。

目前没有考虑到我的接待设置,如下所示:

sock.BeginReceive(_receivedData, 
                  0, 
                  _receivedData.Length, 
                  SocketFlags.None, 
                  OnReceivedData, 
                  sock);

这会将不同的消息作为一条消息接收,以提到的字符分隔。

OnReceivedData(...) 内部,我可以 运行 遍历整个接收到的字节数组,并自己寻找那个特殊字符,但我更希望由套接字处理程序本身处理它。

有谁知道如何声明回调接收以便考虑分隔符,例如(伪代码):

sock.BeginReceive(_receivedData, 
                  0, 
                  _receivedData.Length, 
                  SocketFlags.None, // maybe here?
                  OnReceivedData, 
                  sock, 
                  separator=chr(3));

进一步调查后编辑

关于接收数据的“完整”代码如下所示:

private void SetupReceiveCallback(Socket sock)
{  try
     { sock.BeginReceive(_receivedData, 0, _receivedData.Length, SocketFlags.None, OnReceivedData, sock);}
   catch (Exception ex)
     { }
}

private void OnReceivedData(IAsyncResult ar)
{  sock = (Socket)ar.AsyncState;

   // Check if we got any data
   try
     {
        int nBytesRec = sock.EndReceive(ar);

这(sock.BeginReceive()一次接收一大堆数据,而我希望数据被接收到某个字符(0x03),这是我的消息的终止符.

我自己的答案确实是错误的,因为它需要的数据甚至不完整,造成混乱(正如Dialectus预测的那样)。
至于 Panagiatos 的提议:我对 C# 编程还很陌生。我该怎么做?

提前致谢

此分隔符是您的通信协议的一部分。套接字对应用协议一无所知。他们只知道 TCP/IP。因此,框架无法处理此问题。你必须处理它。您称此字符为分隔符,但它实际上必须是终止符。您的协议必须提供消息结束时的信息,否则您将不知道是否收到了完整的消息。

您获得了字节流,您唯一能保证的是,如果该流存在,那么它具有与发送时相同的字节、相同的顺序。您可能不会收到所有字节,也不能保证您一定会收到。您的通信协议必须足够好以检测流中新消息何时开始以及何时结束。

或者你可以采用一些现有的通信协议,以及实现它的库。

正如许多评论中提到的,在发布问题后,我的应用程序的通信部分无法立即声明分隔符:我只需要从套接字中获取所有内容,然后自己进行分隔,这我喜欢这样:

string [] infoList = infoString.Split('\u0003');
foreach (string infoEntry in infoList)
{
    ... // do the treatment of the messages, one by one

我认为任何回调都不会实现数据包处理。 您需要了解流的利益分离任务 reader 是有效负载(字节)的传递。

正如您提到的分隔符 0x03,实际上这是 ETX(文本结尾),表示任何数据包结尾处的数据结尾。但是在你的情况下,多个消息被 ETX 堆叠在一起。

除非您遵循标准协议(Ymodem、Kermit、Modbus),否则它在很大程度上取决于实施者。

一个好的数据包协议应包括文本开头 (0x02)、字节数、有效负载数据、校验和和文本结尾 (0x03)。

您可能会发现使用 NetworkStream 访问数据更容易。

NetworkStream.ReadByte() method on Microsoft

NetworkStream 构造函数接受 Socket 作为参数。您可以一次读取一个字节来使用一条消息,而不会无意中丢弃任何数据。我相信(不确定)它也会在内部为你缓冲。我认为此方法没有异步版本,因此您还必须考虑到这一点;根据您的代码,我不清楚这是否会产生重大影响。