【问题标题】:How to read from byte stream in Java (PHP/Java socket communication)如何从 Java 中读取字节流(PHP/Java 套接字通信)
【发布时间】:2014-01-20 07:52:46
【问题描述】:

所以。我有一个 PHP 套接字服务器和 Java 套接字客户端。
也许这是一个愚蠢的问题......但我没有找到答案。
在客户端,我需要从输入流中读取传入的字节并将它们放入字节数组中。
我试着这样做:

[客户端(Java)]

public static byte[] read(BufferedInputStream in)
{
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    byte[] buffer = new byte[32768];
    while (true) {
        int readBytesCount = in.read(buffer);
        if (readBytesCount == -1) {
            break;
        }
        if (readBytesCount > 0) {
            baos.write(buffer, 0, readBytesCount);
        }
    }
    baos.flush();
    baos.close();
    return baos.toByteArray();
}

[服务器 (PHP)]

function write(&$client, $message)
{
    $message = explode("\n", $message);
    foreach ($message as $line)
    {
        socket_write($client['sock'], $line."\0");
    }
}

但是当它读取所有字节时,in.read() 不会返回 -1,因此循环不会停止。 一次它返回 13(长度)然后 - 什么都没有。 有什么想法吗?

已解决!
[客户端 (Java)]

ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[32768];
while (true) {
    int readBytesCount = in.read(buffer);
    if (getString(buffer).contains("#!EOS!#")) {
        baos.flush();
        baos.close();
        return baos.toByteArray();
    }
    if (readBytesCount > 0) {
        baos.write(buffer, 0, readBytesCount - 1);
    }
}

[服务器 (PHP)]

function write(&$client, $message)
{
    $message = explode("\n", $message);
    $message = str_replace("\r", "", $message);
    foreach ($message as $line)
    {
        rLog("Write to ".$client['ip'].": ".$line);
        socket_write($client['sock'], $line."\0") or die("[".date('Y-m-d H:i:s')."] Could not write to socket\n");
    }
    socket_write($client['sock'], "#!EOS!#");
}

【问题讨论】:

  • @user2310289 我认为关闭流或类似的东西有问题...
  • 读取字节后(它们已经在缓冲区中),将它们附加到另一个数组中。我不确定这是否会导致您的问题。
  • @user2310289 我会在 2 小时内试试。

标签: java php sockets


【解决方案1】:

如果您的套接字仍然打开,我相信 read 永远不会返回 -1。您没有关闭传输(就文件而言,没有达到 EOF)。我相信当您的消息结束时您的 read 调用会返回 0 (而不是 -1 )。

Java 文档: 读取返回: * 指定的字节数已被读取, * 底层流的read方法返回-1,表示文件结束,或者 * 底层流的可用方法返回零,表示进一步的输入请求会阻塞。

所以我认为您需要发送一个终止字符序列,或者您将发送的字符数,以便在客户端识别数据流中数据块(消息)的边界。

【讨论】:

  • 谢谢。查看更新的问题...也许我可以在那里优化?
  • 发送作为前 2 或 4 个字节的消息的字节数可以避免在收到的每一组数据上执行字符串“#!EOF!#”的搜索(复杂性平均为 O(N) )。使用消息的长度,您可以简单地对读取的数据执行减法运算,从而了解消息何时结束( == 0 )或另一个消息何时已经跟随第一个(
【解决方案2】:

我同意 Stefano 的观点。 php 服务器端没有发生 EOF 或终止信号。 socket_write 只是将 $message 写入客户端。如果您的意图是在整个消息写入后终止连接,那么您可能必须显式使用 socket_shutdown/socket_close。

您也可以尝试使用带有标志的 socket_send。这是http://www.php.net/manual/en/function.socket-send.php的文档@

【讨论】:

  • 谢谢。我更新了问题。也许我可以在那里优化?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-28
  • 2012-05-16
  • 2013-10-12
  • 2015-09-01
  • 2016-02-11
相关资源
最近更新 更多