Java - 如何在字符串套接字之间有效地发送二进制数据?

时间:2014-10-23 15:19:09

标签: java sockets

我正在制作一个聊天程序,我必须将文件分成1024字节块并以此格式通过Socket发送:

<DataPacket>Binary_data<DataPacket\>

目前,我唯一的想法是发送一个字符串

"<Packet>"

然后是字节[1024],然后是字符串

"<Packet\>".

所以我的问题是:

  • 有更方便的方法吗?

  • 哪个输入/输出Java类(DataInputStream,BufferedOutputStream,...)最合适,以及一个小例子代码?

其他信息:

  • 我必须使用Java库(JRE8),没有Apache,......

  • 我知道我不必在TCP中分离数据,这只是必须的。

  • 如果所有代码都可以从以下函数运行,那将是非常好的。

    void SendFile(Socket sendingSocket, File fileToSend);
    void ReceiveFile(Socket receivingSocket);
    

1 个答案:

答案 0 :(得分:0)

要块化二进制数据,通常最好先发送字节数,然后再将原始数据作为字节发送。所以你的聊天客户端应首先发送字符串"Packet 711\n",然后发送文件的711个字节(大多数文件大小不是1024的倍数!)。

这样,您可以以块的形式发送数据,并使最后一个块尽可能小,以避免损坏文件。大小之后的换行使收件人更容易确定数字的结束位置以及真实原始数据的开始位置。

[编辑] 如果您无法更改协议,可能会有效:<DataPacket>711\n ... 711字节二进制数据... </DataPacket> < / p>

因此发送数据的代码如下所示:

void SendFile(Socket sendingSocket, File fileToSend) {
    OutputStream stream = sendingSocket.getOutputStream();
    InputStream input = new FileInputStream(fileToSend);

    byte[] buffer = new byte[1024];
    int len;
    while(true) {
        len = input.read(buffer);
        if(len < 0) break;

        String header = "<DataPacket>" + len + "\n";
        stream.write(header.getBytes('ASCII'));
        stream.write(buffer, 0, len);
        String footer = "<DataPacket\>";
        stream.write(footer.getBytes('ASCII'));
    }

    input.close();
    stream.close();
}

在接收端,您需要解析标头(包括要使用的字节数)。然后你可以分配一个缓冲区并读取字节。