[英]Cannot read from stream (IOException: non-blocking socket would block) using Bouncy Castle with Xamarin and Java Server
Prerequisites: I'm using Xamarin to write a mobile app which should exchange small message chunks with a java server. 先决条件:我正在使用Xamarin编写一个移动应用程序,该应用程序应与Java服务器交换小消息块。 I'm using the .NET implementation of Bouncy Castle for sending data over TLS, since I'm restricted to a specific cipher suite (TLS_ECDH_anon_WITH_AES_256_CBC_SHA) which is not supported by default for Android phones above API Level 23.
我使用Bouncy Castle的.NET实现通过TLS发送数据,因为我仅限于特定的密码套件(TLS_ECDH_anon_WITH_AES_256_CBC_SHA),默认情况下,API级别23以上的Android手机不支持该密码套件。
The problem: If I only try to send data via the following code, everything is fine. 问题:如果我仅尝试通过以下代码发送数据,一切都很好。 But if I try to also read the response back, the stream hangs for some seconds and then throws the exception
System.IO.IOException: Unable to read data from the transport connection: Operation on non-blocking socket would block.
但是,如果我尝试也读回响应,则流挂起几秒钟,然后引发异常
System.IO.IOException: Unable to read data from the transport connection: Operation on non-blocking socket would block.
However, as you can see in the example below, I'm initializing Bouncy Castle's TlsClientProtocol with the "blocking"-constructor (docu says it is blocking if a stream is given), so the socket should not be non-blocking. 但是,正如您在下面的示例中看到的那样,我正在使用“阻塞”构造函数初始化Bouncy Castle的TlsClientProtocol(docu表示如果提供了流,它将阻塞),因此套接字不应是非阻塞的。
Furthermore, the server receives the data almost instantly, but only if no reading from the client will follow in code. 此外,服务器几乎立即接收数据,但前提是没有来自客户端的读取将跟随代码。 If a
.Read(..)
or .DataAvailable
check comes afterwards, the server receives the data after the exception occurred or it does not receive anything. 如果之后出现
.DataAvailable
.Read(..)
或.DataAvailable
检查,则服务器将在发生异常后接收数据,或者不接收任何数据。
Purged/simplified code version: 清除/简化的代码版本:
Clientside Xamarin app: 客户端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);
Server side java application (I have no access to it, but i got the info that it is implemented that way): 服务器端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);
Some of the failed solution attempts so far: 到目前为止,一些失败的解决方案尝试:
So, I'm actually starting to tear my hairs out of my head. 因此,我实际上开始从头上拔掉头发。 Any help is appreciated!
任何帮助表示赞赏!
EDIT: I fortunately found the solution, it was just a dumb error I made, see my answer below. 编辑:幸运的是,我找到了解决方案,这只是我犯的一个愚蠢的错误,请参阅下面的答案。
It turned out, that the exception message was somehow misleading. 原来,异常消息在某种程度上具有误导性。 The socket was in blocking mode and the mistake was ... how should I call it ... dumb.
套接字处于阻止模式,错误是……我该怎么称呼……愚蠢。 I simply forgot to append a newline (\\n).
我只是忘了添加一个换行符(\\ n)。 This was also the reason why the java server did not receive anything until the TcpClient was disposed - it was waiting for the newline.
这也是Java服务器直到TcpClient被处理之前一直没有收到任何消息的原因-它正在等待换行符。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.