这是在园子维护的开源项目 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 10个月前