簡體   English   中英

使用Bouncy Castle和Xamarin和Java Server無法讀取流(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),默認情況下,API級別23以上的Android手機不支持該密碼套件。

問題:如果我僅嘗試通過以下代碼發送數據,一切都很好。 但是,如果我嘗試也讀回響應,則流掛起幾秒鍾,然后引發異常System.IO.IOException: Unable to read data from the transport connection: Operation on non-blocking socket would block. 但是,正如您在下面的示例中看到的那樣,我正在使用“阻塞”構造函數初始化Bouncy Castle的TlsClientProtocol(docu表示如果提供了流,它將阻塞),因此套接字不應是非阻塞的。

此外,服務器幾乎立即接收數據,但前提是沒有來自客戶端的讀取將跟隨代碼。 如果之后出現.DataAvailable .Read(..).DataAvailable檢查,則服務器將在發生異常后接收數據,或者不接收任何數據。

清除/簡化的代碼版本:

客戶端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-相同的結果

因此,我實際上開始從頭上拔掉頭發。 任何幫助表示贊賞!

編輯:幸運的是,我找到了解決方案,這只是我犯的一個愚蠢的錯誤,請參閱下面的答案。

原來,異常消息在某種程度上具有誤導性。 套接字處於阻止模式,錯誤是……我該怎么稱呼……愚蠢。 我只是忘了添加一個換行符(\\ n)。 這也是Java服務器直到TcpClient被處理之前一直沒有收到任何消息的原因-它正在等待換行符。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM