SslStream的TcpClient.Available等价方法是什么?

9

根据@Len-Holgate在这个问题中的建议,我正在异步请求0字节读取,在回调函数中使用同步读取接受可用字节,因为我知道数据已经准备好且不会阻塞。这似乎非常高效和美妙。

但是当我添加SslStream选项时,这种方法就失败了。零字节读取很好,但SslStream解密字节后,在TcpClient的缓冲区中留下零字节计数(适当地),我无法确定现在有多少字节可供读取。

是否有一种简单的解决办法?


以下是一些代码,仅供参考:

sslStream.BeginRead(this.zeroByteBuffer, 0, 0, DataAvailable, this);

在EndRead()之后(正确返回0),DataAvailable包含:

// by now this is 0, because sslStream has already consumed the bytes
available = myTcpClient.Available; 

if (0 < available) // Never occurs
{
    // this part can be distractingly complicated, but 
    // it's based on the available byte count
    sslStream.Read(...); 
}

由于协议的原因,我需要逐字节评估并解码可变宽度Unicode等内容。我不想异步地逐字节读取!


3
我曾经构建了许多基于 Socket 的应用程序,有的使用 SSL,有的同步或异步。但我从未遇到过需要知道可用字节数的情况。我认为依赖此功能的应用程序是有问题的。请问您的代码为什么需要这个功能?为什么不直接请求与 byteBuffer.Length 相同数量的字节呢? - dtb
1
因为我不知道在这种情况下需要接收多少字节才能获得换行符。如果我请求1024个字节,那么回调函数将一直等待直到有1024个字节可用(或由于套接字关闭而达到流的末尾)。除非我对此有误解? - Jason Kleban
2
无论是Read还是BeginRead,它们只会返回当前可用的数据,除非没有数据可用,在这种情况下,它们将等待至少一个字节变为可用或流被关闭。例如,如果您请求1024个字节,它们将返回1到1024个字节之间的数据,但不会等待直到接收到完整的1024个字节。 - dtb
3
你可以使用BeginRead请求0个字节,当回调函数被调用时,你可以使用Read请求byteBuffer.Length个字节来检索可用的字节。只需确保你的缓冲区足够大,或者最好分多次检索可用字节。请注意,由于TCP是流而不是消息定向的,因此分隔符不能保证恰好出现在可用字节块的末尾。因此,你仍然需要在缓冲区中进行一些缓冲和查找分隔符。 - dtb
2
只有在没有可用字节时才读取块。但是,由于您知道字节可用(因为已调用回调),因此可以安全地调用Read而不必担心它会阻塞。话虽如此,我不确定直接使用BeginRead读取字节比异步等待字节并同步读取它们更糟糕的原因。 - dtb
显示剩余3条评论
1个回答

1
如果我理解正确,您的消息是由某个特定字符分隔的,并且您已经使用了一个StringBuilder来处理当消息被分成多个部分的情况。 您可以考虑在读取数据时忽略分隔符,当数据可用时将任何数据添加到其中,然后检查本地的StringBuilder以查找分隔符字符。 找到后,您可以使用sb.ToString(0, delimiterIndex)sb.Remove(0, delimiterIndex)提取单个消息,直到没有分隔符为止。 这也涵盖了同时接收两条消息的情况。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接