无法使用 Bouncy Castle 与 Xamarin 和 Java Server 从流读取(IOException:非阻塞套接字会阻塞)

2023-12-29

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

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

此外,服务器几乎立即接收数据,但前提是客户端不会在代码中读取数据。如果一个.Read(..) or .DataAvailablecheck是事后发生的,服务器在异常发生后才收到数据或者没有收到任何东西。

清除/简化的代码版本:

客户端 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);

迄今为止一些失败的解决方案尝试:

  • 手动设置 client.Client.Blocking = false -- 没有任何改变
  • 异常表示套接字是非阻塞的,因此我尝试通过 protocol.Stream.DataAvailable 在循环中等待——它一直在等待,但是在我退出应用程序后,服务器收到了消息(在循环期间没有收到任何消息)由服务器)
  • 我编写了自己的 java 服务器来在本地主机上测试此行为 - 相同的结果
  • 我尝试使用 BeginSend / BeginRead - 相同的结果

所以,我实际上已经开始拔掉我的头发了。任何帮助表示赞赏!

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


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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

无法使用 Bouncy Castle 与 Xamarin 和 Java Server 从流读取(IOException:非阻塞套接字会阻塞) 的相关文章

随机推荐