这是在园子维护的开源项目 EnyimMemcachedCore 中遇到的一个问题,当前的读取代码如下
public async Task ReadAsync(byte[] buffer, int offset, int count)
{
int read = 0;
int shouldRead = count;
while (read < count)
{
int currentRead = _useSslStream
? await _sslStream.ReadAsync(buffer, offset, shouldRead).ConfigureAwait(false)
: await _inputStream.ReadAsync(buffer, offset, shouldRead).ConfigureAwait(false);
if (currentRead == count)
break;
if (currentRead < 1)
throw new IOException("The socket seems to be disconnected");
read += currentRead;
offset += currentRead;
shouldRead -= currentRead;
}
}
目前有2个 issue 反馈不能正常读取:
改为下面的读取代码进行验证
int currentRead = -1;
do
{
currentRead = await _sslStream.ReadAsync(buffer, offset, shouldRead).ConfigureAwait(false);
}
while (currentRead != 0);
在使用 SslStream
读取 Socket 数据时,确保正确处理 SSL/TLS 连接的特性是非常重要的。您提供的代码看起来基本上是正确的,但有几个地方可以改进,特别是针对 SSL 连接的处理。以下是一些建议和改进的代码示例:
检查 SSL 连接状态:
处理部分读取:
SslStream.ReadAsync
可能会返回少于请求字节数的字节,因此需要在循环中处理。增加超时和取消支持:
CancellationToken
来支持取消操作,以避免在网络问题时无限等待。增强错误处理:
以下是根据上述建议改进后的 ReadAsync
方法:
public async Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken = default)
{
int read = 0;
int shouldRead = count;
while (read < count)
{
// 检查是否取消了操作
cancellationToken.ThrowIfCancellationRequested();
int currentRead;
try
{
currentRead = _useSslStream
? await _sslStream.ReadAsync(buffer, offset + read, shouldRead, cancellationToken).ConfigureAwait(false)
: await _inputStream.ReadAsync(buffer, offset + read, shouldRead, cancellationToken).ConfigureAwait(false);
}
catch (IOException ex)
{
// 处理 IOException,可能是连接问题
throw new IOException("An error occurred while reading from the stream.", ex);
}
if (currentRead == 0)
{
// 连接已关闭
throw new IOException("The socket seems to be disconnected");
}
read += currentRead;
shouldRead -= currentRead;
}
}
CancellationToken
支持,允许在需要时取消读取操作。ReadAsync
调用中,使用 offset + read
而不是 offset
,确保从正确的位置开始读取。IOException
并提供更具体的错误信息,帮助调试。通过以上改进,您可以提高 SslStream
的读取稳定性和错误处理能力。如果问题仍然存在,请考虑检查网络连接、SSL 配置以及 AWS Memcached 的特定要求。如果有其他问题或需要进一步的帮助,请随时询问!
Why does SslStream.Read always set TcpClient.Available to 0, when NetworkStream.Read doesn't
– dudu 2周前