如何使用相同的套接字发送二进制文件和文本

时间:2013-09-06 07:19:30

标签: java android sockets networking concurrency

我必须将一个短字符串作为文本从客户端发送到服务器,然后发送一个二进制文件。

如何使用相同的套接字连接发送二进制文件和字符串?

服务器是Java桌面应用程序,客户端是Android平板电脑。我已经将其设置为在两个方向上在客户端和服务器之间发送文本消息。我还没有完成二进制文件发送部分。

一个想法是设置两个单独的服务器同时运行。我认为如果我使用两个不同的端口号并在应用程序中的两个不同线程上设置服务器,这是可能的。我将不得不设置在Android应用程序中的两个服务上运行的两个并发客户端。

另一个想法是以某种方式使用if else语句来确定发送两种类型文件中的哪一种(二进制文本),并使用适当的方法接收正在发送的文件类型的文件。

发送文字的示例代码

 PrintWriter out;
 BufferedReader in;

out = new PrintWriter(new BufferedWriter
(new OutputStreamWriter(Socket.getOutputStream())) true,);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

out.println("test out");
String message = in.readLine();

发送二进制文件的示例代码

 BufferedOutputStream out;
 BufferedInputStream in;
 byte[] buffer = new byte[];
 int length = 0;

 out = new BufferedOutputStream(new FileOutputStream("test.pdf));
 in = new BufferedInputStream(new FileOutputStream("replacement.pdf"));

 while((length = in.read(buffer)) > 0 ){
 out.write(buffer, 0, length);
 }

3 个答案:

答案 0 :(得分:6)

我不认为在你的情况下使用两个线程是必要的。只需使用socket的{​​{1}}和InputStream,即可在发送短信后发送二进制数据。

服务器代码

OutputStream

客户代码

OutputStream stream = socket.getOutputStream();
PrintWriter out = new PrintWriter(
    new BufferedWriter(
        new OutputStreamWriter(stream)
    )
);
out.println("test output");
out.flush(); // ensure that the string is not buffered by the BufferedWriter

byte[] data = getBinaryDataSomehow();
stream.write(data);

为了在客户端确定正确的InputStream stream = socket.getInputStream(); String message = readLineFrom(stream); int dataSize = getSizeOfBinaryDataSomehow(); int totalBytesRead = 0; byte[] data = new byte[dataSize]; while (totalBytesRead < dataSize) { int bytesRemaining = dataSize - totalBytesRead; int bytesRead = stream.read(data, totalBytesRead, bytesRemaining); if (bytesRead == -1) { return; // socket has been closed } totalBytesRead += bytesRead; } ,您必须以某种方式传输二进制块的大小。您可以在服务器代码中dataSize之前将其作为字符串发送,或将其作为二进制数据的一部分。在后一种情况下,前四个或八个字节可以保存二进制数据的实际长度,以字节为单位。

希望这有帮助。


修改

正如@EJP正确指出的那样,在客户端使用out.flush()可能会导致二进制数据损坏或丢失,因为BufferedReader“窃取”二进制数据中的某些字节以填充其缓冲区。相反,您应该自己读取字符串数据,并查找分隔符或通过其他方式传输字符串数据的长度。

BufferedReader

答案 1 :(得分:0)

您可以阅读有关HTTP协议如何工作的内容,它实质上发送了“ascii和人类可读”标题(可以这么说),之后可以使用适当的编码添加任何内容,例如base64。你可以自己创造类似的东西。

答案 2 :(得分:0)

你需要首先发送字符串,然后发送字节数组的大小,然后发送字节数组,使用String.startsWith()方法检查发送的内容。