1

我有一个关于 HTTPS 套接字如何工作的问题。

我必须在移动设备和服务器之间实现双向通信。

我从蓝牙设备以原始字节的形式获取请求,但请求是以块的形式接收的,并且它以相同的方式等待响应。我的意思是:设备正在向我发送一个块,我必须将其发送到服务器,并且我必须将服务器响应发送回设备,以接收第二个块。

好吧,这一次有效,我的意思是我正在打开套接字,正在编写请求块,正在读取响应块,但是当我编写第二个请求块时,没有从套接字接收到数据。

代码如下所示:

if (webSocket == null) {
    SocketFactory factory = SSLSocketFactory.getDefault();
    webSocket = factory.createSocket(DataUtils.stringValueFromByteArray(requestPackage.getHostAddress()),
                                                   DataUtils.intValueFromByteArray(requestPackage.getHostPort()));

}
 webInputStream = webSocket.getInputStream();
 webOutputStream = webSocket.getOutputStream();


 webOutputStream.write(requestPackage.getDataContent(), 0,requestPackage.getDataContent().length);
 webOutputStream.flush();

byte[] byteBuffer = getBytesFromInputStream(webInputStream);

getBytesFromInputStream 看起来像:

public static byte[] getBytesFromInputStream(InputStream is)
        throws IOException {



    ByteArrayOutputStream bout = new ByteArrayOutputStream();
    byte buf[] = new byte[8192];
    int ret = 0;
    while ((ret = is.read(buf)) != -1) {
        bout.write(buf, 0, ret);
    }

    byte[] bytes = bout.toByteArray();
    return bytes;
}

webSocket请求开始时获取一个值,null并且连接不应该结束。

现在的问题是这段代码适用于第一个数据块,但在第二个数据块上,getButesFromInputStream返回一个空数组,因为is.read()立即返回 -1。

任何人都可以建议我该怎么做,或者向我解释我做错了什么?

任何帮助,将不胜感激。谢谢,阿克德

4

3 回答 3

1

TCP 的一个常见误解是,接收应用程序会以与发送应用程序发送数据的方式相同的块中获取数据片段。TCP 所保证的只是顺序(以及最终交付,前提是没有错误):这应该被视为一个整体的流。

为此原因:

  • 读取 0 字节并不表示套接字已关闭(也是一个常见的误解)
  • 应用协议必须定义分隔符或替代方式来告诉对方何时停止读取,以便能够处理应用协议的各种命令。

HTTP 1.1 使用header 来告诉在请求/响应或Chunked Transfer-EncodingContent-Length的主体中必须读取多少字节,而在发送 header 时不知道大小。

如果您想读取 HTTP 请求/响应,您需要处理:标头以空行终止,正文的长度由Content-Length您获得的 或 各种块给出。

如果您想读取内容长度,自己实现这一点相对简单,但如果您还希望能够处理分块传输编码,则肯定需要更多的工作。总的来说,你不妨使用一个 HTTP 库,它会为你做这一切。正如尼古拉所说,HttpsURLConnection是一个好方法。如果这不能满足您的需求,您可以使用 Apache Http Client 库(也随 Android AFAIK 提供)。

于 2012-10-24T12:41:17.907 回答
1

如果您确实在使用 HTTPS,请不要使用原始套接字,而是使用HttpsURLConnection理解该协议的类似 HTTP 客户端。然后来自 BT 的每个下一个块将作为一个新请求发送到服务器。

于 2012-10-24T07:01:00.810 回答
0

in getBytesFromInputStream,在你的 while 之前,添加另一个 while :

while (is.available() == -1) {
    Thread.sleep(100); // for instance. less may very well work too.
}

这将等待一些数据可供读取。(数据到达服务器、服务器回复、数据到达您的时间。)

编辑

由于某种原因 is.available() 似乎返回 0,您可以使用 is.read 代替:

while (ret = (is.read(buf)) <= 0) {
    Thread.sleep(100); // for instance. less may very well work too.
}
bout.write(buf, 0, ret);

(额外的写入避免丢失实际读取的数据。)

这个想法是等到从服务器收到一些答案,然后实际读取它。

于 2012-10-24T12:04:02.183 回答