无法使用带有 Xamarin 和 Java 服务器的 Bouncy Castle 从流中读取(IOException:非阻塞套接字会阻塞)

Cannot read from stream (IOException: non-blocking socket would block) using Bouncy Castle with Xamarin and Java Server

先决条件: 我正在使用 Xamarin 编写一个移动应用程序,它应该与 java 服务器交换小消息块。 我正在使用 Bouncy Castle 的 .NET 实现通过 TLS 发送数据,因为我仅限于特定的密码套件 (TLS_ECDH_anon_WITH_AES_256_CBC_SHA),Android 以上的手机默认不支持 API 23级.

问题:如果我只尝试通过以下代码发送数据,一切都很好。但是如果我也尝试读取响应,流会挂起几秒钟然后抛出异常 System.IO.IOException: Unable to read data from the transport connection: Operation on non-blocking socket would block. 但是,正如您在下面的示例中看到的,我正在初始化 Bouncy Castle 的 TlsClientProtocol "blocking"-构造函数(docu 说如果给定一个流它就会阻塞),所以套接字不应该是非阻塞的。

此外,服务器几乎立即接收到数据,但前提是没有来自客户端的读取会在代码中跟进。如果随后出现.Read(..).DataAvailable检查,则服务器在异常发生后接收数据或没有接收到任何数据。

Purged/simplified代码版本:

客户端 Xamarin 应用程序:

TcpClient client = new TcpClient() { ReceiveTimeout = 5000, SendTimeout = 5000 };
client.Connect(ip, port);
NetworkStream stream = client.GetStream();

TlsClientProtocol protocol =
    new TlsClientProtocol(stream, new Org.BouncyCastle.Security.SecureRandom());
protocol.Connect(new CustomTlsClient()); // CustomTlsClient derives from DefaultTlsClient and is used to overwrite the CipherSuite
protocol.Stream.Write(data, 0, data.length);
protocol.Stream.Flush();
// Sending won't work too if the following line is present
protocol.Stream.Read(buffer, 0, buffer.Length);

服务器端 java 应用程序(我无法访问它,但我得到的信息是它是以这种方式实现的):

SSLServerSocket socket = (SSLServerSocket)SSLServerSocketFactory.getDefault().createServerSocket(port);
String[] enabledCipherSuites = new String[] { "TLS_ECDH_anon_WITH_AES_256_CBC_SHA" };
socket.setEnabledCipherSuites(enabledCipherSuites);

SSLSocket clientSocket = socket.accept();
clientSocket.startHandshake();
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);

String request = in.readLine(); // Works only if the client won't read afterwards
out.println(request);

到目前为止一些失败的解决方案尝试:

所以,我实际上已经开始抓狂了。感谢您的帮助!

编辑:幸运的是我找到了解决方案,这只是我犯的一个愚蠢的错误,请参阅下面的答案。

事实证明,异常消息在某种程度上具有误导性。套接字处于阻塞模式,错误是……我该怎么称呼它……愚蠢。我只是忘了添加换行符 (\n)。这也是为什么 java 服务器在处理 TcpClient 之前没有收到任何东西的原因 - 它正在等待换行符。